The 15th Zhejiang University Programming Contest

参考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 998244353
using 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章