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