题意
题解
这个题目把和式用人话说一遍就是:对于n个数,两两之和的x次方的值全部相加。
我们先用二项式定理把式子展开:
((a_i+a_j)^n=sum_{k=0}^{n} inom{n}{k}a_i^{n-k}a_j^k)
因为数据范围的限制,我们只能逐个数考虑贡献,首先考虑(a_i)对每个x次方的贡献,观察二项式展开的结果显然有一个((n-1)a_i^x)贡献,但其他项不方便直接提取
对于一个(inom{n}{k}a_i^{n-k}a_j^k),j可以取除i以外所有数,于是有
[inom{n}{k}a_i^{n-k}(a_{j_1}^k+a_{j_2}^k+...)=inom{n}{k}a_i^{n-k}(sum_k-a_i^k)
]
其中(sum_k=sum a_i^k)
这样我们可以依次计算出每一位对于x次方的贡献,当然这样((a_i+a_j)^x)和((a_j+a_i))会被重复计算,结果还需要除以2,最后加上((n-1)a_i^x)贡献
因为(sum_k)和(inom{n}{m})可以预处理出来,所以时间复杂度为(O(nk))。
具体细节见代码
代码
/*************************************************************************
> File Name: 2.cpp
> Author: Knowledge_llz
> Mail: 925538513@qq.com
> Blog: https://blog.csdn.net/Pig_cfbsl
> Created Time: 2020/10/24 21:01:12
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define LL long long
using namespace std;
int read(){
char x=getchar(); int u=0,fg=0;
while(!isdigit(x)){ if(x=='-') fg=1; x=getchar(); }
while(isdigit(x)){ u=(u<<3)+(u<<1)+(x^48); x=getchar(); }
return fg?-u:u;
}
const int maxx=2e5+10,mod=998244353;
LL n,k,a[maxx][320],sum[320],ans[320],c[320][320];
void init(){
For(i,0,300) c[0][i]=1;
For(i,1,300) For(j,1,i)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
LL qpow(LL x,LL y){
LL res=1;
while(y){
if(y&1) res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
init();
LL inv=qpow(2,mod-2);
n=read(); k=read();
For(i,1,n){
a[i][1]=read();
For(j,2,k) a[i][j]=a[i][j-1]*a[i][1]%mod;
}
For(i,1,k) For(j,1,n) (sum[i]+=a[j][i])%=mod;
For(i,1,k)
For(j,1,k-i){
ans[i+j]=(ans[i+j]+c[i+j][i]*sum[i]%mod*sum[j]%mod)%mod;
}
For(i,2,k){
(ans[i]-=(qpow(2,i)-2)*sum[i]%mod)%=mod;
ans[i]=ans[i]*inv%mod;
}
For(i,1,k){
(ans[i]+=sum[i]*(n-1)%mod)%=mod;
printf("%lld
",(ans[i]+mod)%mod);
}
return 0;
}