题目:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5480
题意:
给出n和k, 求出n个数的任意非空子集的最大公约数的k次方的期望, 最后求出期望*(2^n-1)
思路:
每取一个子集的概率都为 1/(2^n-1), 结果除以(2^n-1),则实际上是求出每个非空子集的k次方的和.
题目转化为gcd为i的子集为多少, 枚举i 从MAX到1.
对于每个i, 求出n个数中为i 的倍数为cnt个,
则gcd=i 的非空子集的个数dp[i] = (2^cnt-1) - dp[j] (j为i 的倍数).
AC.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const ll mod = 998244353;
int sum[maxn];
ll dp[maxn];
ll cal(ll x, int n)
{
ll s = 1;
while(n > 0) {
if(n & 1) s = (s*x) % mod;
x = (x*x)%mod;
n >>= 1;
}
return s;
}
int main()
{
//freopen("in", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
int n, k;
scanf("%d %d", &n, &k);
memset(sum, 0, sizeof(sum));
memset(dp, 0, sizeof(dp));
int MAX = 0;
for(int i = 0; i < n; ++i) {
int a;
scanf("%d", &a);
MAX = max(MAX, a);
sum[a]++;
}
ll ans = 0;
for(int i = MAX; i >= 1; --i) {
int cnt = 0;
for(int j = i; j <= MAX; j+=i) {
cnt += sum[j];
dp[i] = (dp[i] - dp[j] + mod) % mod;
}
dp[i] = ((dp[i]+cal(2, cnt)-1)%mod + mod) % mod;
ans = (ans + dp[i]*cal(i, k)) % mod;
}
printf("%lld\n", ans);
}
return 0;
}