The 15th Zhejiang University Programming Contest

来源:互联网 发布:淘宝关联页是什么 编辑:程序博客网 时间:2024/05/02 06:12

参考http://www.kuangbin.net/archives/15th_zju
I-GCD Expectation
http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5471

///参考了kuangbin大神的#include <iostream>#include <cstdio>#include <cstring>#define max(a,b)  (a)>(b)?(a):(b)#define N 1000002#define mod 998244353using namespace std;int b[N];long long dp[N];long long pow_m(long long a,long long n){    long long ret = 1;    long long tmp = a;    while(n){        if(n&1)ret = ret*tmp%mod;        tmp = tmp*tmp%mod;        n >>= 1;    }    return ret;}int main(){    int t;   scanf("%d",&t);       int n,k;       while(t--){            scanf("%d%d",&n,&k);            memset(b,0,sizeof(b));            int temp,max0=-1;///找出最大数            for(int i=0;i<n;i++){                scanf("%d",&temp);                b[temp]++;///集合中有重复的数,建个表方便查                max0=max(max0,temp);            }            long long sum=0;            int cnt;///计算i倍数的个数            for(int i=max0;i>=1;i--)            {                dp[i]=0;                cnt=0;                for(int j=i;j<=max0;j=j+i){///顺便求了倍数                    cnt+=b[j];///记了有多少个                    if(j>i)dp[i]=(dp[i]-dp[j]+mod)%mod;///计算gcd为i的子集个数,需要减去i的倍数才是他单独的                }///求和                ///那么如果i的倍数有x个, 那么gcd为 i的倍数的子集个数就是 2^x - 1                dp[i]=(dp[i]+pow_m(2,cnt)-1+mod)%mod;                sum+=dp[i]*pow_m(i,k)%mod;///按要求求和                sum%=mod;            }            cout<<sum<<endl;       }    return 0;}
0 0