BZOJ(本校) 3027 快速傅里叶变换 - 概率与期望&dp

来源:互联网 发布:橱柜设计软件下载 编辑:程序博客网 时间:2024/05/18 00:37

题目描述
有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] = 2t -1
那么根据容斥原理,令g[i]表示选出的数所得的gcd是i的方案数
则:

g[i]=f[i]ji,1<=j<=mg[j]

ans=ni=1ig[i]

不要忘记%Mod哦,前面的推导都没有写%Mod

#include<cstdio>#define MAXN 100000#define Mod 998244353typedef 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;}
0 0
原创粉丝点击