CF1618E Singers' Tour

image

比较水的推柿子


手玩样例不难发现:

\[\begin{cases} b_1=a_1+na_2+(n-1)a_3+...+2a_n \\ b_2=2a_1+(2-1)a_2+na_3+...+3a_n \\ ... \\ b_n=na_1+(n-1)a_2+(n-2)a_3+...+a_n \end{cases} \]

肯定不能高斯消元因为时间复杂度到了 \(O(n^3)\),考虑瞪眼法解方程。

瞪眼后将其整理不难发现:

\[\sum \limits _{i=1}^{n} {b_{i}}=\sum \limits _{i=1}^{n} \sum \limits _{j=1}^{n}{a_{i}\times {}j}=\sum \limits _{i=1}^{n} a_i\frac{(n+1)n}{2} \]

移项后可得:

\[\sum \limits _{i=1}^{n} b_i \div \frac{(n+1)n}{2}=\sum \limits _{i=1}^{n} a_i \]

\(b\) 做差分,发现:

\[b_{i}-b_{i-1}=(\sum \limits _{i=1}^{n} a_i)-a_i\times n \]

代入并移项:

\[a_i\times n=\sum \limits _{i=1}^{n} b_i \div \frac{(n+1)n}{2}-(b_i-b_{i-1}) \]

解得:

\[a_i=\frac{\sum \limits _{i=1}^{n} b_i \div \frac{(n+1)n}{2}-(b_i-b_{i-1})}{n} \]

啊真是一场酣畅淋漓的解方程啊

随后用结论计算即可。

其中输出 NO 仅当 \(a_i<0\)\(a_i\) 出现小数。

code:

%:include<bits/stdc++.h>
inline int read()<%
	int s=0;
	int w=1;
	char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())
    	if(ch=='-')
			w=-1;
	for(;ch>='0' and ch<='9';ch=getchar())
		s=s*10+ch-'0';
	return s*w;
%>

void write(int x)<%
	if(x<0)<%
   		putchar('-');
   		x=-x;
	%>
	if(x>9)
    	write(x/10);
	putchar(x%10+'0');
	return;
%>//快读快写自动掠过,考虑到数据较大建议使用

int t;
int n;
double b[40086];
double a[40086];
signed main(){
	t=read();
	while(t--){
		double sum=0;
		n=read();
		bool flag=false;
		for(int i=1;i<=n;i++){
			b[i]=read();
			sum+=b[i];//统计bi之和
		}
		a[1]=(sum/(n*(n+1.00)/2.00)-(b[1]-b[n]))/n;//特别地计算a1
		for(int i=1;i<=n;i++){
			if(i!=1)
				a[i]=(sum/(n*(n+1.00)/2.00)-(b[i]-b[i-1]))/n;//可爱的结论
			if(ceil(a[i])!=a[i] or a[i]<=0){//骚操作,若取整与它本身大小不同就出现了小数
				flag=true;//打标记输出比较方便
				break;
			}
		}
		if(flag){
			puts("NO");
			continue;
		}
		else{
			puts("YES");
			for(int i=1;i<=n;i++){
				write(a[i]);
				std::cout<<" ";
			}
			puts("");
			continue;
		}
	}
	return 0;//撒花
}
posted @ 2024-07-23 16:35  立花廿七  阅读(4)  评论(0编辑  收藏  举报