2015多校联合训练赛 Training Contest 4 1008

时间:2024-01-07 21:12:38

构造题:

比赛的时候只想到:前面一样的数,后面 是类似1,2,3,4,5,6....t这 既是:t+1,t+1...,1,2,3,...t

t+1的数目 可能 很多,

题解时YY出一个N 然后对N  判断。

seg{Li*(Li-1)} = n*n+n-2*k=d;

每次跑sqrt(n)找到 最近的 d ,D_new=d-Li*(Li-1);

这样一定能解的:d 一定是偶数,Li*(Li-1)也一定是偶数,2*1=2;

还有seg(Li)=n;

当Li=1是 Li*Li-Li=0;

加入一些1就好。

思路有了,建议自己实现一下。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll; #define N 10234567
int a[N];
int b[N]; int main()
{ int n;
freopen("input.txt","r",stdin);
freopen("out.txt","w",stdout);
while (scanf("%d",&n)!=EOF) //注意我这里 K N 的位置相反
{
int t=;
if (n<=)// 特判 N<=100;
{
printf("%d\n",n);
for (int i=;i<n;i++) printf("%d ",);
printf("%d\n",);
}
else
{
ll k=;
for (int i=;i<=sqrt(*n)+;i++) //由题解 随便指定一个 N--> 就是k
{
ll ttt=(ll) i*(i+)/-n;
if (ttt>=)
{
k=i;
break;
}
}
k++;// 稍微大一点也没关系的
ll tmp=k*(k+)/-n;//题解没除二 ,我除了 ,其实都是一样的 while (tmp)//每次找一个p p*(p-1)<=tmp;
{
int pos=;
for (int i=;i<=sqrt(tmp)+;i++)
{
if (tmp>=(ll) i*(i-)/) pos=i;
else break;
}
a[++t]=pos;
tmp-=(ll) pos*(pos-)/;
} int res=;
for (int i=;i<=t;i++) res+=a[i]; if (res<k) //res一定<=k验证的很多数据
for (int i=;i<=k-res;i++)
a[++t]=; int id=;
for (int i=;i<=t;i++)
for (int j=;j<=a[i];j++)
b[++id]=i; printf("%d\n",id); for (int i=;i<id;i++) printf("%d ",b[i]);
printf("%d\n",b[id]);
}
}
return ;
}