Zoj 3868 GCD Expectation

2019-07-15 16:34:47 浏览数 (1)

给一个集合,大小为n , 求所有子集的gcd 的期望和 。 

期望的定义为 这个子集的最大公约数的K次方 ; 

每个元素被选中的概率是等可能的

即概率 p = (发生的事件数)/(总的事件数);

总的事件数 = 2^n -1; 大小为n的集合的非空子集个数为2^n -1

期望 = p(i) *i;  

       = 1*p(1) 2*p(2) ... n*p(n);

设x发生的事件数为 dp[x] , 则上式可化简为:

       =1*dp[1]/(2^n-1) 2*dp[2]/(2^n-1) ... n*dp[n]/(2^n-1);

       =1/(2^n-1)*(1*dp[1] 2*dp[2] ... n*dp[n]);

题目要求最后所得结果乘以 (2^n-1);

所以式子最后化简为:1*dp[1] 2*dp[2] ... n*dp[n]

即问题转化为求gcd = i 的子集数

假设gcd = m*i (m = 0,1,2,3,... && m*i <= max_num)的个数为dp[i]个

那么gcd = i 的个数则为 for(int j= i i ; j <= max_num ; j = i) dp[i]-=dp[j] ;

则期望为:dp[1] * 1^k dp[2] * 2^k ... dp[i] * i^k ;

代码语言:javascript复制
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <iostream>
 6 #include <map>
 7 #include <list>
 8 #include <queue>
 9 #include <stack>
10 #include <string>
11 #include <algorithm>
12 #include <iterator>
13 using namespace std;
14 #define MAXN 1000010
15 #define INF 0x3f3f3f3f
16 #define MOD 998244353
17 #define eps 1e-6
18 #define LL long long 
19 int num[MAXN];
20 LL dp[MAXN];
21 //dp[i] = 2^x -1 ; gcd = n*i;
22 //for(int j = i ; j <= max_num ; j  = i) dp[i] -= dp[j];
23 LL qpow(LL x , LL k)
24 {
25     LL res=1;
26     while(k)
27     {
28         if(k & 1) res = res * x % MOD;
29         x = x * x % MOD;
30         k >>= 1;
31     }
32     return res;
33 }
34 
35 int main()
36 {
37     int T;
38     int n,k;
39     LL ans;
40     scanf("%d",&T);
41     while(T--)
42     {
43         scanf("%d %d",&n,&k);
44         int x;
45         int max_num = 0;
46         int cunt = 0;
47         memset(num , 0 , sizeof(num));
48         memset(dp , 0 , sizeof(dp));
49         for(int i = 0 ; i < n ; i   )
50         {
51             scanf("%d",&x);
52             num[x]   ;
53             max_num = max(x , max_num);
54         }
55 
56         ans = 0;
57         for(int i = max_num ; i >= 1 ; i --)
58         {
59             cunt = 0;
60             dp[i] = 0;
61             for(int j = i ; j <= max_num ; j  = i)
62             {
63                 cunt  = num[j];
64                 if(j > i) dp[i] = (dp[i] - dp[j]   MOD) % MOD;
65             }
66             dp[i] = (dp[i]   qpow(2 , cunt) - 1   MOD) % MOD;
67             ans = (ans   (dp[i] * qpow(i , k)) % MOD ) % MOD;
68         }
69         printf("%dn",(int)ans);
70     }
71     return 0;
72 }

0 人点赞