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] = 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 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章