poj3904容斥原理

来源:互联网 发布:yum安装命令 编辑:程序博客网 时间:2024/05/21 08:59

题意:从若干个数中找出a,b,c,d满足gcd(a,b,c,d)=1,求组数。
分析:我们从反面来考虑,即求出有多少组是不满足要求的。
把每个数素数分解,记录不重复素因子所能组成的因子,把这些因子的总数统计,并且统计每个因子是由多少个素因子组成 。
比如:这n个数中只含有2,3这两个质因数,且质因数中含2的有a个,含3的有b个,含6(2*3)的有c个,那么答案便是C(n,4)-(C(a,4)+C(b,4)-C(c,4))。
下面是代码^_^:

#include<cstdio>#include<cstring>using namespace std;const int maxn=10010;typedef long long LL;LL p[maxn];LL count[maxn];LL prime[maxn];LL num[maxn];void init(){    LL i;    for(i=4;i<=maxn;i++) p[i]=i*(i-1)*(i-2)*(i-3)/(LL)24;}void solve(LL n){    LL cnt=0;    for(LL i=2;i*i<=n;i++){        if(n%i==0) prime[++cnt]=i;        while(n%i==0) n/=i;    }    if(n!=1) prime[++cnt]=n;    for(LL i=1;i<(1<<cnt);i++){        LL k=1;        LL sum=0;        for(LL j=1;j<=cnt;j++){            if(i & (1<<(j-1))){                k*=prime[j];                sum++;            }        }        count[k]++;        num[k]=sum;    }}int main(){    init();    LL n,i,m;    while(scanf("%lld",&n)!=EOF){        memset(count,0,sizeof(count));        for(i=1;i<=n;i++){            scanf("%lld",&m);            solve(m);        }        LL ans=0;        for(i=1;i<=maxn;i++){            if(count[i]){                if(num[i]%2) ans+=p[count[i]];                else ans-=p[count[i]];            }        }        printf("%lld\n",p[n]-ans);    }    return 0;}
1 0
原创粉丝点击