CF1081E Solution

题目链接

题解

\(\sum\limits_{i=1}^{2k}x_i\)\(sum\),因为前缀和均为完全平方数,可以设整数\(b^2=sum+x_{2k+1},a^2=sum+x_{2k+1}+x_{2k+2}\)。进一步推导得\(a^2-b^2=x_{2k+2}\),所以\(x_{2k+2}=(a+b)(a-b)\)。因此我们可以枚举\(x_{2k+2}\)的因数\(y,z(y\cdot z=x_{2k+2},y\ge z)\),如果\(y,z\)同奇同偶则一定可以解出\(a,b\)\(a=\frac{y+z}{2},b=\frac{y-z}{2}\),同奇偶时存在整数解)。而\(x_{2k+1}=b^2-sum\)。当存在多组符合条件的因数时,我们需取\(y,z\)最接近的一组。此时\(y+z,y-z\)最小,解出的\(a,b\)也最小,因为存在答案上界,利用贪心思想可知这样最优。

具体实现:枚举\(k\)(其实就是枚举偶数项),分解\(x_{2k+2}\),记录答案,如果无\(a,b\)正整数解则判断无法构造,如果可以更新\(sum\)的值。

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,inf=0x3f3f3f3f3f3f3f3f;
int x[N],y[N];//x:偶数项,y:奇数项
signed main()
{
	int n,sum=0;
	scanf("%lld",&n);
	for(int i=1;i<=n/2;i++) scanf("%lld",&x[i]);
	memset(y,0x3f,sizeof(y)); 
	for(int i=1;i<=n/2;i++)//枚举偶数项(k=i-1)
	{
		for(int j=1;j*j<=x[i];j++)//分解偶数项
		{
			if(x[i]%j) continue;  
			if(j%2==x[i]/j%2)//如果同奇同偶
			{
				int b=(x[i]/j-j)/2,t=b*b-sum;//t:当前解出的奇数项
				if(t>0) y[i]=min(y[i],t);
			}
		}
		if(y[i]==inf) {printf("No"); return 0;}//如果无正整数解
		sum+=x[i]+y[i];//更新sum
	}
	printf("Yes\n");
	for(int i=1;i<=n/2;i++) printf("%lld %lld ",y[i],x[i]);
	return 0;
}
posted @ 2021-02-03 20:57  violet_holmes  阅读(39)  评论(0编辑  收藏  举报