2020CCPC 长春 L. Coordinate Paper(思维,构造)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020CCPC 长春 L. Coordinate Paper(思维,构造)相关的知识,希望对你有一定的参考价值。

LINK

构造数组满足

Ⅰ . a i > 0 Ⅰ.a_i>0 .ai>0

Ⅱ . ∑ i = 1 n a i = s Ⅱ.\\sum\\limits_{i=1}^na_i=s .i=1nai=s

Ⅲ . i ∈ [ 1 , n − 1 ] , a i − a i + 1 = k Ⅲ.i\\in[1,n-1],a_i-a_{i+1}=k .i[1,n1],aiai+1=k a i + 1 − a i = 1 a_{i+1}-a_i=1 ai+1ai=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=1nai)%(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=1nai=x

此时需要满足 x < s & & ( x − s ) % ( k + 1 ) = = 0 x<s\\&\\&(x-s)\\%(k+1)==0 x<s&&(xs)%(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=(ai1+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)

2020 CCPC 长春 K. Ragdoll(预处理+启发式合并)

2017CCPC 长春