ZOJ 3868 GCD Expectation

GCD Expectation

Time Limit: 4000ms
Memory Limit: 262144KB
This problem will be judged on ZJU. Original ID: 3868
64-bit integer IO format: %lld      Java class name: Main
 

Edward has a set of n integers {a1, a2,...,an}. He randomly picks a nonempty subset {x1, x2,…,xm} (each nonempty subset has equal probability to be picked), and would like to know the expectation of [gcd(x1, x2,…,xm)]k.

Note that gcd(x1, x2,…,xm) is the greatest common divisor of {x1, x2,…,xm}.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains two integers nk (1 ≤ nk ≤ 106). The second line contains n integers a1, a2,…,an (1 ≤ ai ≤ 106).

The sum of values max{ai} for all the test cases does not exceed 2000000.

Output

For each case, if the expectation is E, output a single integer denotes E · (2n - 1) modulo 998244353.

Sample Input

1
5 1
1 2 3 4 5

Sample Output

42

Source

Author

LIN, Xi
 
解题:我们采取的是枚举gcd的策略
真子集的个数为$2^{cnt}-1$个数
但是我们发现,算我们枚举的gcd的时候,真正的gcd确实我们枚举的gcd的倍数
所以要去重,利用容斥原理
 
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int mod = 998244353;
 5 const int maxn = 1000010;
 6 LL dp[maxn];
 7 int sum[maxn];
 8 LL quickPow(LL base,int index){
 9     LL ret = 1;
10     while(index){
11         if(index&1) ret = ret*base%mod;
12         index >>= 1;
13         base = base*base%mod;
14     }
15     return ret;
16 }
17 int main(){
18     int kase,n,k,mxv,tmp;
19     scanf("%d",&kase);
20     while(kase--){
21         scanf("%d%d",&n,&k);
22         memset(sum,0,sizeof sum);
23         for(int i = mxv = 0; i < n; ++i){
24             scanf("%d",&tmp);
25             sum[tmp]++;
26             mxv = max(mxv,tmp);
27         }
28         LL ret = 0;
29         for(int i = mxv; i > 0; --i){
30             int cnt = dp[i] = 0;
31             for(int j = i; j <= mxv; j += i){
32                 dp[i] = (dp[i] - dp[j] + mod)%mod;
33                 cnt += sum[j];
34             }
35             dp[i] = (dp[i] + quickPow(2,cnt) - 1)%mod;
36             ret = (ret + dp[i]*quickPow(i,k))%mod;
37         }
38         printf("%lld
",ret);
39     }
40     return 0;
41 }
View Code
原文地址:https://www.cnblogs.com/crackpotisback/p/4784679.html