标签:
题意:
给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