AtCoder Regular Contest 106 D Powers 解题报告

传送门

题意

题解

这个题目把和式用人话说一遍就是:对于n个数,两两之和的x次方的值全部相加。
我们先用二项式定理把式子展开:
\((a_i+a_j)^n=\sum_{k=0}^{n} \binom{n}{k}a_i^{n-k}a_j^k\)
因为数据范围的限制,我们只能逐个数考虑贡献,首先考虑\(a_i\)对每个x次方的贡献,观察二项式展开的结果显然有一个\((n-1)a_i^x\)贡献,但其他项不方便直接提取
对于一个\(\binom{n}{k}a_i^{n-k}a_j^k\),j可以取除i以外所有数,于是有

\[\binom{n}{k}a_i^{n-k}(a_{j_1}^k+a_{j_2}^k+...)=\binom{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\)\(\binom{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\n",(ans[i]+mod)%mod);
	}
	
	return 0;
}
posted @ 2020-10-26 22:42  Knowledge-Pig  阅读(344)  评论(0编辑  收藏  举报