2020CCPC 长春 L. Coordinate Paper(思维,构造)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020CCPC 长春 L. Coordinate Paper(思维,构造)相关的知识,希望对你有一定的参考价值。
构造数组满足
Ⅰ . a i > 0 Ⅰ.a_i>0 Ⅰ.ai>0
Ⅱ . ∑ i = 1 n a i = s Ⅱ.\\sum\\limits_{i=1}^na_i=s Ⅱ.i=1∑nai=s
Ⅲ . i ∈ [ 1 , n − 1 ] , a i − a i + 1 = k Ⅲ.i\\in[1,n-1],a_i-a_{i+1}=k Ⅲ.i∈[1,n−1],ai−ai+1=k或 a i + 1 − a i = 1 a_{i+1}-a_i=1 ai+1−ai=1至少有一个满足
先考虑构造一个最小和的解,形如
0 1 2 … k 0 1 2 … k 0 1 …
可以算得这个答案为 w w w
若 s < w s<w s<w显然无解,否则考虑是否存在解
若想增大答案,无非是在某个减 k k k的地方改为加 1 1 1
实质上就是把序列中的 0 0 0依次变为 k + 1 k+1 k+1
若还想增大答案,就可以把序列中的 1 1 1依次变成 k + 2 k+2 k+2
可以发现,在一次操作中,我们总是把减 k k k的地方改为加 1 1 1
每次都把序列和增大 k + 1 k+1 k+1,并且不会漏掉中间的值
所以当确定 a 1 % ( k + 1 ) a_1\\%(k+1) a1%(k+1)时, ( ∑ i = 1 n a i ) % ( k + 1 ) (\\sum\\limits_{i=1}^na_i)\\%(k+1) (i=1∑nai)%(k+1)也被唯一确定
我们可以枚举 a 1 % ( k + 1 ) = x a_1\\%(k+1)=x a1%(k+1)=x,那么此时构造的最小解相当于
x (x+1)%(k+1) (x+2)%(k+1) … (x+n-1)%(k+1)
这个答案可以直接算到,计算是否等于 s % ( k + 1 ) s\\%(k+1) s%(k+1)
于是我们拿到合法的 x x x值,就可以逐步增加凑到 s s s了
注意
枚举 a 1 a_1 a1的初值时,算得 ∑ i = 1 n a i = x \\sum\\limits_{i=1}^na_i=x i=1∑nai=x
此时需要满足 x < s & & ( x − s ) % ( k + 1 ) = = 0 x<s\\&\\&(x-s)\\%(k+1)==0 x<s&&(x−s)%(k+1)==0
然后根据 a 1 a_1 a1的初值复原初始序列 a i = ( a i − 1 + 1 ) % ( k + 1 ) a_i=(a_{i-1}+1)\\%(k+1) ai=(ai−1+1)%(k+1)
于是接下来可以从小到大对每个数加上 k + 1 k+1 k+1了
但是这样太慢,我们可以先对整体加上 c ∗ ( k + 1 ) c*(k+1) c∗(k+1)( c c c由计算得到)
然后每次对一个数加 k + 1 k+1 k+1,这样总的操作复杂度控制在 O ( n + k ) O(n+k) O(n+k)内
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5+10;
int n,k,s,a[maxn];
int get(int n)//首项为0,公差为1,长度为n且对k+1取模的数列和
{
int duan = n/(k+1), yu = n%(k+1);
int sum = (k+1)*k/2*duan+yu*(yu-1)/2;
return sum;
}
void ok(int sum)
{
if( sum!=s ) return;
for(int i=1;i<=n;i++) printf("%lld ",a[i] );
exit(0);
}
signed main()
{
cin >> n >> k >> s;
int chu = -1, he = 0;
for(int i=0;i<=k;i++)//枚举a[1]的初值
{
int now = min( n,k+1-i );//可以构造now次
int pre = now*i+now*(now-1)/2;
int sum = pre+get( n-now );
if( sum > s || sum%(k+1)!=s%(k+1) ) continue;
chu = i, he = sum;
break;
}
if( chu==-1 ){ printf("-1"); return 0; }
a[1] = chu;
for(int i=2;i<=n;i++) a[i] = ( a[i-1]+1 )%(k+1);
int x = ( s-he )/( n*(k+1) );//整体加x次
for(int i=1;i<=n;i++) a[i] += x*(k+1);
he += x*n*(k+1);
ok(he);
for(int i=0;i<=k;i++)//从初始数字为i的开始加k+1
{
int pos = (k+1-chu)+i+1;
if( i>=chu ) pos = i-chu+1;
for(int j = pos;j<=n; j+= (k+1) )
{
a[j] += (k+1); he += (k+1);
ok(he);
}
}
}
以上是关于2020CCPC 长春 L. Coordinate Paper(思维,构造)的主要内容,如果未能解决你的问题,请参考以下文章
2020 ccpc长春 D. Meaningless Sequence(按位启发式合并)
2020第6届中国大学生程序设计竞赛CCPC长春站, 签到题3题
2020第6届中国大学生程序设计竞赛CCPC长春站, 签到题3题
2020 CCPC 长春 J. Abstract Painting(状压dp)