Solution to Luogu P6340

[Problem Discription]\color{blue}{\texttt{[Problem Discription]}}[Problem Discription]

[Analysis]\color{blue}{\texttt{[Analysis]}}[Analysis]

题目相当于给出以下 nnn 个方程:

{an+a1+a2=b1a1+a2+a3=b2a2+a3+a4=b3⋯an−1+an+a1=bn\begin{cases} &a_{n} &+ &a_{1} &+ &a_{2} &= &b_{1}\\ &a_{1} &+ &a_{2} &+ &a_{3} &= &b_{2}\\ &a_{2} &+ &a_{3} &+ &a_{4} &= &b_{3}\\ &\cdots\\ &a_{n-1} &+ &a_{n} &+ &a_{1} &= &b_{n} \end{cases}⎩ ⎨ ⎧ana1a2⋯an−1++++a1a2a3an++++a2a3a4a1====b1b2b3bn

把所有方程相加,我们可以得到最终构造的数组一定满足条件 111: ∑i=1nai=13∑i=1nbi\sum\limits_{i=1}^{n} a_{i}=\dfrac{1}{3} \sum\limits_{i=1}^{n}b_{i}i=1∑nai=31i=1∑nbi。记该数为 tar\text{tar}tar。

同时,通过方程之间相互消元可以得到

ai+3=ai+bi+2−bi+1(∗)a_{i+3}=a_{i}+b_{i+2}-b_{i+1}\quad (*)ai+3=ai+bi+2−bi+1(∗)

即若 aia_{i}ai 已知,则 ai+3,ai+6,⋯a_{i+3},a_{i+6},\cdotsai+3,ai+6,⋯ 均已知。

如果 nmod  3≠0n \mod 3 \not= 0nmod3=0,那么只需要给定 A1A_{1}A1,就可以通过 (∗)(*)(∗) 式算出所有的 A2⋯nA_{2 \cdots n}A2⋯n。但是这个数列不一定满足条件 111。没关系,我们记 sum=∑i=1nAi\text{sum}=\sum\limits_{i=1}^{n} A_{i}sum=i=1∑nAi,则 AiA_{i}Ai 相对 aia_{i}ai 的进动量为 −tar−sumn-\dfrac{\text{tar}-\text{sum}}{n}−ntar−sum,修正后即可得到正确答案。

如果 nmod  3=0n \mod 3 = 0nmod3=0,则需要给定 A1,2,3A_{1,2,3}A1,2,3 才能确定整个数列。注意,这三个数不能随便给,因为后面修正的时候每个数都减去相同的数,因此每三个数的和一定增大 333 的倍数(包括负倍数),所以必须保证初始的 A1+A2+A3 mod a1+a2+a3≡3A_{1}+A_{2}+A_{3} \bmod a_{1}+a_{2}+a_{3} \equiv 3A1+A2+A3moda1+a2+a3≡3。

Code\color{blue}{\text{Code}}Code

cpp 复制代码
```const int N=1e4+100;
typedef long long ll;

int b[N],a[N],n;
bool vis[N];
ll sum,tar,reg;

int add(int a,int b){
	if (a+b>n) return a+b-n;
	else return a+b;
}

void manifest(int pos,int val){
	int cur=pos,lst=add(cur,3);
	
	a[pos]=val;
	vis[pos]=true;
	
	while (!vis[lst]){
		vis[lst]=true;
		a[lst]=a[cur]+b[add(cur,2)]-b[add(cur,1)];
		
		cur=lst;
		lst=add(cur,3); 
	}
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
		tar+=b[i];
	}
	
	if (tar%3){
		printf("No Solution");
		return 0;
	}
	
	tar/=3;
	
	if (n%3) manifest(1,46);
	else{
		manifest(1,18);
		manifest(2,26);
		manifest(3,b[2]-44);
	}
	
	for(int i=1;i<=n;i++)
		sum+=a[i];
	
	reg=(tar-sum)/n;
	
	for(int i=1;i<=n;i++)
		a[i]+=reg; 
	
	for(int i=1;i<=n;i++)
		printf("%d ",a[i]);
	
	return 0;
}
相关推荐
Z9fish1 小时前
sse哈工大C语言编程练习20
c语言·开发语言·算法
晓13131 小时前
第六章 【C语言篇:结构体&位运算】 结构体、位运算全面解析
c语言·算法
iAkuya2 小时前
(leetcode)力扣100 61分割回文串(回溯,动归)
算法·leetcode·职场和发展
梵刹古音2 小时前
【C语言】 指针与数据结构操作
c语言·数据结构·算法
VT.馒头2 小时前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
CoderCodingNo3 小时前
【GESP】C++五级练习题 luogu-P1865 A % B Problem
开发语言·c++·算法
大闲在人3 小时前
7. 供应链与制造过程术语:“周期时间”
算法·供应链管理·智能制造·工业工程
小熳芋3 小时前
443. 压缩字符串-python-双指针
算法
Charlie_lll4 小时前
力扣解题-移动零
后端·算法·leetcode
chaser&upper4 小时前
矩阵革命:在 AtomGit 解码 CANN ops-nn 如何构建 AIGC 的“线性基石”
程序人生·算法