题解:P11277 世界沉睡童话
Pro
构造序列 ,长度为 ,并使得序列有 组倍数关系。
要求:。
Sol
我们最好让这个序列有序,因为这样只有后面的数对前面的数有倍数关系。
首先我们发现, 中间是没有倍数关系的。
我们还发现,如果有 个相同的数 ,它对答案的贡献为 。
最后我们发现,在 个 的基础上,再添加一个 ,会增加 组倍数关系。
我们发现特殊性质有一栏是这么写的:
。
这说明我们可以在 时,将其缩小到范围 。
这里使用性质 3,在前面疯狂添加 ,直到 。
while(n<=k+1&&n!=0)
{
cout<<"1 ";
n--;
k-=n;
}
如果此时 ,可以直接 return 0; 了。
如果此时 ,因为 ,所以 ,也就是说如果我们可以从前往后填 ,从后往前填 ,且不重复。
使用性质 2,一直枚举最大的 使得 ,然后填上 个 ,再使 加 。初始 。
最后 的时候,从 开始,从后往前填即可。
以上全部运用了性质 3。
时间复杂度是 的。
void ans(int n,int k)
{
while(n<=k+1&&n!=0)
{
cout<<"1 ";
n--;
k-=n;
}
if(n<=0) return;
int a=n,lst=n;
while(k&&lst)
{
int sum=sqrt(k)*2;
while(sum*(sum-1)/2>k)sum--; // 这里应该可以直接用数学推出来
k-=sum*(sum-1)/2;
for(int i=1;i<=sum;i++) cout<<a<<' ';
lst-=sum,a++;
}
for(int i=2*n-1;lst;i--) cout<<i<<' ',lst--;
}

浙公网安备 33010602011771号