CF1618E Singers' Tour
比较水的推柿子
手玩样例不难发现:
\[\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;//撒花
}