• AtCoder Regular Contest 106 D Powers 解题报告


    传送门

    题意

    题解

    这个题目把和式用人话说一遍就是:对于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;
    }
    
  • 相关阅读:
    POJ-1318(list.sort()输出不为字典序,map才是按字典序排列)
    C++ 进阶
    命令模式在MVC框架中的应用
    使用NoSQL Manager for MongoDBclient连接mongodb
    第一部分 学习函数式思维
    【剑指offer】复杂链表的复制
    Hadoop-2.4.0分布式安装手冊
    Impala中多列转为一行
    js(jquery)绑定点击事件
    hdu1243 最长公共子序列(LCS)
  • 原文地址:https://www.cnblogs.com/Knowledge-Pig/p/13881915.html
Copyright © 2020-2023  润新知