题意简述
给定一个 n ( < = 1 e 9 ) n(<=1e9) n(<=1e9),构造一个序列使得:
- [ 1 , n ] [1,n] [1,n]中所有整数是这个序列中某些元素的和
- 字典序最小
输出这个序列
思路
我们一开始认为: n n n是 1 e 9 1e9 1e9,这个序列怎么也是 1 e 8 1e8 1e8,但是为什么还要输出呢?不是要 O L E OLE OLE。。。
仔细想想,并不是这样的。此时我突然想起了我们***初中初一期末考试题。和这个题一模一样,只是 n = 15 n=15 n=15。
我当时构造了一个 1 , 2 , 4 , 8 1,2,4,8 1,2,4,8。当时我的数学水平还没有现在掉的这么严重(只有全市前 100 100 100),那个时候我是前 20 20 20(我在江苏省苏州市)。对于当时做数学题经验丰富的我来说,构造这个并不难。
回忆一下当时的构造方法, 1 , 2 , 4 , 8 1,2,4,8 1,2,4,8。没错,我们只要类似“二进制拆分”就珂以了!!!所以,粗略估计答案长度是 l o g n logn logn级别的,即使 n = 1 e 9 n=1e9 n=1e9,也只有 30 30 30多一点。
但是并不是所有时候都是直接二进制拆分的,我们还要保证字典序最小。比如 n = 6 n=6 n=6的时候,应该是 1 , 2 , 3 1,2,3 1,2,3,而不是 1 , 2 , 4 1,2,4 1,2,4。这个问题很好解决,我们只要把暴力二进制拆分中的下取整改成上取整就好了。(即 ( n + 1 ) / 2 (n+1)/2 (n+1)/2)
代码:
#include<bits/stdc++.h>
using namespace std;
namespace Flandle_Scarlet
{
int n;
void Soviet()
{
int cnt=0;
int a[40];
while(n)
{
a[++cnt]=(n+1)/2;//这里改成(n+1)/2
n>>=1;
}
printf("%d\n",cnt);
sort(a+1,a+cnt+1);
for(int i=1;i<=cnt;++i)
{
printf("%d ",a[i]);
}putchar('\n');
}
void IsMyWife()
{
if (0)
{
freopen("","r",stdin);
freopen("","w",stdout);
}
cin>>n;
Soviet();
}
};
int main()
{
Flandle_Scarlet::IsMyWife();
return 0;
}

该博客主要解析了洛谷2320和bzoj1192题目,涉及如何构造一个序列,使得[1, n]中的所有整数都是序列中元素的和,并保证序列字典序最小。作者通过回忆初中时期的类似问题,提出采用类似二进制拆分的方法,即按位上取整,来解决构造序列的问题。预计序列长度为logn级别,对于n=1e9的情况,也只需约30步。博客提供了问题的解决思路,并未展示具体代码。"
139323119,9280705,畅捷通T+软件业务流程详解,"['会计软件', '企业管理', '业务流程', '账务处理', 'T+软件']
672

被折叠的 条评论
为什么被折叠?



