BZOJ(本校) 3027 快速傅里叶变换 - 概率与期望&dp
题目描述
有n 颗珠子,珠子的编号依次为1 到n。第i 颗珠子的美丽值为vi,这是一个在1 到m 之间的正整数。
查尔明将会从中等概率随机抽取1 到n 颗珠子,那么此时他的高兴度为所有抽到的珠子的美丽值的最大公约数。查尔明想知道,他的期望高兴度是多少,你能帮帮他吗?因为查尔明不喜欢实数和大数,所以你只需要输出结果×(2^n − 1) 的值对998244353 取模的结果即可。
输入
n, m
v1, v2, ……,vn
输出
答案
样例输入
3 4
2 4 3
样例输出
14
提示
对于30% 的数据,n ≤ 20,m ≤ 100000。
对于另外30% 的数据,n ≤ 100000,m ≤ 20。
对于100% 的数据,n ≤ 100000,m ≤ 100000。
来源
Claris
分析:
先求出1~m中,每个数出现的次数,记为a[]。
令f[i]表示选出的数所得的gcd是i的倍数的方案数,t为在给出的n个数中i的倍数出现的次数
则:f[i] =
那么根据容斥原理,令g[i]表示选出的数所得的gcd是i的方案数
则:
ans=
不要忘记%Mod哦,前面的推导都没有写%Mod
#include<cstdio>
#define MAXN 100000
#define Mod 998244353
typedef long long LL;
LL n,m,a[MAXN+10],f[MAXN+10],g[MAXN+10],P[MAXN+10],ans;
int main()
{
LL x;
scanf("%I64d%I64d",&n,&m);
for(LL i=1;i<=n;i++){
scanf("%I64d",&x);
a[x]++;
}
P[0]=1;
for(LL i=1;i<=n;i++)
P[i]=P[i-1]*2%Mod;
for(LL i=1;i<=m;i++){
LL cnt=0;
for(LL j=i;j<=m;j+=i)
cnt+=a[j];
f[i]=(P[cnt]-1)%Mod;
}
for(LL i=m;i>=1;i--){
LL sum=0;
for(LL j=i+i;j<=m;j+=i)
sum=(sum+g[j])%Mod;
g[i]=(f[i]-sum+Mod)%Mod;
}
for(LL i=1;i<=m;i++)
ans=(ans+i*g[i]%Mod)%Mod;
printf("%lld\n",ans);
return 0;
}