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;
}
相关推荐
万添裁9 分钟前
huawei 机考
算法·华为·深度优先
IronMurphy7 小时前
【算法四十三】279. 完全平方数
算法
墨染天姬8 小时前
【AI】Hermes的GEPA算法
人工智能·算法
papership8 小时前
【入门级-数据结构-3、特殊树:完全二叉树的数组表示法】
数据结构·算法·链表
smj2302_796826528 小时前
解决leetcode第3911题.移除子数组元素后第k小偶数
数据结构·python·算法·leetcode
Beginner x_u9 小时前
链表专题:JS 实现原理与高频算法题总结
javascript·算法·链表
_深海凉_12 小时前
LeetCode热题100-寻找两个正序数组的中位数
算法·leetcode·职场和发展
旖-旎13 小时前
深搜练习(电话号码字母组合)(3)
c++·算法·力扣·深度优先遍历
谭欣辰13 小时前
C++快速幂完整实战讲解
算法·决策树·机器学习
Mr_pyx13 小时前
【LeetHOT100】随机链表的复制——Java多解法详解
算法·深度优先