- 比赛的时候榜带偏了,导致L没开出来,当时思路想的挺对了,但觉得好像不是很对,最后没尝试,最后三题遗憾铜牌第二。今天补出来了。。。
题意很清晰,让你构造一个n的序列,要么ai=ai-1+1;
要么ai=a[i-1]-k。和为S,首先我们去想什么时候不行,也就是构造这个序列的最小值,一定是0123…k0123…k这样构造,而且这个最小值可以用前缀和计算得出,而且很关键的一个地方就是,我们构造的这个和最小的系列,可以通过整体都加(k+1)的倍数,或某个可以增加k+1,而且对于k来说,我们以开头构造的序列的和可以包括到所有%(k+1)的情况,比如4 2 11:
构造开头: 0120 和为3%3=0 11%3=2 1201 4 1 2012 5 2
所以2012 可以构造出11的和,11-5=6 6/(k+1)=2 所以将两个数+(k+1)即可。总复杂度接近O(k+n);
而且最后加的时候我是直接暴力加的,57ms。
在这里插入代码片
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
typedef long long ll;
using namespace std;
#define rep(i,j,n) for(ll i=j;i<=n;i++)
#define per(i,j,n) for(ll i=j;i>=n;i--)
typedef unsigned long long ull;
typedef unsigned short us;
const ll INF= 1e18+7;
const ll maxx = 1e6+7;
const ll mod= 1e9+7;
const double eps=1e-8;
inline bool read(ll &num){char in;bool IsN=false;in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,k,q;
ll a[maxx];
ll sum[maxx];
ll b[maxx];
int main()
{
ll t;
ll s;
cin>>n>>k>>s;
sum[0]=0;
a[0]=0;
rep(i,1,k)
{
a[i]=i;
sum[i]=sum[i-1]+i;
}
ll nn=max(n,k);
rep(i,k+1,2*nn+100)
{
sum[i]=i%(k+1);
a[i]=i%(k+1);
sum[i]+=sum[i-1];
}
rep(i,0,k)
{
ll num;
if(i==0) num=sum[n-1];
else num=sum[i+n-1]-sum[i-1];
ll p=s-num;
if(p>=0&&p%(k+1)==0 )
{
ll geshu=p/(k+1) ;
ll zhi=geshu/n;
rep(j,i,i+n-1) a[j]+=zhi*(k+1);
geshu=geshu%n;
while(1)
{
if(geshu==0) break;
rep(j,i,i+n-1)
{
if(j==i)
{
if(a[j]+k+1-a[j+1]==k || a[j]+k+1==a[j+1]-1 )
{
a[j]+=k+1;
geshu--;
}
}
else if(j==i+n-1)
{
if(a[j]+k+1==a[j-1]-k|| a[j]+k+1==a[j-1]+1 )
{
a[j]+=k+1;
geshu--;
}
}
else
{
ll x=a[j]+k+1;
if( (x==a[j-1]+1||x==a[j-1]-k)&&(x==a[j+1]-1||x==a[j+1]+k) )
{
a[j]+=k+1;
geshu--;
}
}
if(geshu==0) break;
}
if(geshu==0) break;
}
rep(j,i,i+n-1) printf("%lld ",a[j]);
printf("\n");
return 0;
}
}
printf("-1\n");
return 0;
}