标签:
题意:
给n和k,求n个数的任意非空子集gcd的k次方的期望。
最后期望乘上2^n-1
思路:
因为取每个子集都是等概率,所以取出每个子集的概率是1/(2^n-1)
然而最后的答案是乘上2^n-1
所以其实求的就是每个非空子集的gcd的k次方的和。
然后就是求法了。
我们可以把题目转换成求gcd等于i的非空集合有多少个。
gcd从Max枚举到1,求出答案。
对于每个i,设n个数中是i的倍数的数有x个。
那么gcd等于i的个数就是总共的 (2^x-1)个减去gcd等于j的个数,j是i的倍数。
因此要从大到小过一遍。
代码:
#include"stdio.h" #include"algorithm" #include"string.h" #include"iostream" #include"queue" #include"map" #include"string" #define mod 998244353 #define ll long long using namespace std; int sum[2002000],a[1234567]; int dp[2002000]; ll power(ll a,int k) { ll b=1; while(k) { if(k&1) b=(b*a)%mod; a=(a*a)%mod; k/=2; } return b; } int main() { int t; cin>>t; memset(sum,0,sizeof(sum)); while(t--) { int n,k,Max=0; scanf("%d%d",&n,&k); for(int i=0;i<n;i++) { scanf("%d",&a[i]); Max=max(a[i],Max); sum[a[i]]++; } for(int i=0;i<=Max;i++) dp[i]=0; ll ans=0; for(int i=Max;i>=1;i--) { int tep=0; for(int j=i;j<=Max;j+=i) { tep+=sum[j]; dp[i]=(dp[i]-dp[j]+mod)%mod; } dp[i]=((dp[i]+power(2,tep)-1)%mod+mod)%mod; ans=(ans+dp[i]*power(i,k))%mod; } for(int i=0;i<n;i++) sum[a[i]]--; //减少每次memset的时间 printf("%lld\n",ans); } return 0; }
[暴力统计] zoj 3868 GCD Expectation
标签:
原文地址:http://blog.csdn.net/wdcjdtc/article/details/45023591