poj 3904 莫比烏斯反演 或 容斥原理
阿新 • • 發佈:2019-02-01
poj 3904 莫比烏斯反演 或 容斥原理
題目:
給出n個數字a1,a2,...an, 求從中選出一個四元組(a,b,c,d), 使得gcd(a,b,c,d)=1,求符合條件的四元組的數目。
限制:
1 <= n <= 1e4; 1 <= ai <= 1e4
思路:
莫比烏斯反演入門題
設f(k)為gcd(a,b,c,d)=k的四元組的數目,
設F(k)為gcd(a,b,c,d)為k的倍數的四元組的數目,
F(k)可以通過這個方式得到:
先通過對每個ai分解因數預處理處理出來,對於每個k,有多少個ai是它的倍數,假設為m,然後F(k)=C(m,4)。
令lim=max(a1,a2,...,an)
最後f(1)=mu[1]*F(1) + mu[2]*F(2) + ... + mu[lim]*F(lim)
同樣用容斥也可以做
題目:
給出n個數字a1,a2,...an, 求從中選出一個四元組(a,b,c,d), 使得gcd(a,b,c,d)=1,求符合條件的四元組的數目。
限制:
1 <= n <= 1e4; 1 <= ai <= 1e4
思路:
莫比烏斯反演入門題
設f(k)為gcd(a,b,c,d)=k的四元組的數目,
設F(k)為gcd(a,b,c,d)為k的倍數的四元組的數目,
F(k)可以通過這個方式得到:
先通過對每個ai分解因數預處理處理出來,對於每個k,有多少個ai是它的倍數,假設為m,然後F(k)=C(m,4)。
令lim=max(a1,a2,...,an)
最後f(1)=mu[1]*F(1) + mu[2]*F(2) + ... + mu[lim]*F(lim)
/*poj 3904 題目: 給出n個數字a1,a2,...an, 求從中選出一個四元組(a,b,c,d), 使得gcd(a,b,c,d)=1,求符合條件的四元組的數目。 限制: 1 <= n <= 1e4; 1 <= ai <= 1e4 思路: 莫比烏斯反演入門題 設f(k)為gcd(a,b,c,d)=k的四元組的數目, 設F(k)為gcd(a,b,c,d)為k的倍數的四元組的數目, F(k)可以通過這個方式得到: 先通過對每個ai分解因數預處理處理出來,對於每個k,有多少個ai是它的倍數,假設為m,然後F(k)=C(m,4)。 令lim=max(a1,a2,...,an) 最後f(1)=mu[1]*F(1) + mu[2]*F(2) + ... + mu[lim]*F(lim) */ #include #include #include #include using namespace std; #define LL __int64 const int N=100005; int cnt[N]; int mu[N]; void getMu(){ for(int i=1;in-m;--i) ret*=(LL)i; for(int i=2;i<=m;++i) ret/=i; return ret; } LL gao(int x,int c){ LL ret=C(c,4); return mu[x]*ret; } int main(){ getMu(); int n,a,_max; while(scanf("%d",&n)!=EOF){ _max=0; memset(cnt,0,sizeof(cnt)); for(int i=0;i=4) ans+=gao(i,cnt[i]); } printf("%I64d\n",ans); } return 0; }
同樣用容斥也可以做
#include #include #include #include using namespace std; #define LL __int64 const int N=100005; int cnt[N]; LL C(int n,int m){ if(nn-m;--i) ret*=(LL)i; for(int i=2;i<=m;++i) ret/=i; return ret; } LL gao(int x,int c){ LL ret=C(c,4); int lim=sqrt(x); int flag=0; for(int i=2;i<=lim;++i){ if(x%i==0){ ++flag; x/=i; } if(x%i==0) return 0; } if(x!=1) ++flag; if(flag%2==0) return ret; else return -ret; } int main(){ int n,a,_max; while(scanf("%d",&n)!=EOF){ _max=0; memset(cnt,0,sizeof(cnt)); for(int i=0;i=4) ans+=gao(i,cnt[i]); } printf("%I64d\n",ans); } return 0; }