poj 3904 求四元互质集合

  从给定的集合中求互质四元组的个数。
  解题思路:先求解非互质四元组的个数,在总体四元组个数减去这个数目。求非互质四元组即求公因数大于1的四元组数目,因此,使用公因数d把集合中的元素划分成不同的子集,每个子集中的四元组一定是非互质的。还有一点需要考虑的是,不同子集中可能蕴含相同的非互质四元组。可以使用容斥原理解决这个问题,具体的方法是对公因数d进行质因数分解,若d可以分解成奇数个质数,就在非互质四元组总数中加上公因数d对应的非互质四元组,若为偶数则减去。

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;

int cnt[10010];  //记录每个因数对应子集的元素数
int num[10010];  //记录每个因数分解的不同质因数个数
int prime[5];  //记录一个数字对应的质因数(10000以内最多有五个不同质因数)
long long p[10010]={0}; //记录组合数

void solve(int n)
{
    int tol=0;
    for(int i=2;i*i<=n;i++) //求输入数字的质因数,方法很好
    {
        if(n%i==0)
            prime[tol++]=i;
        while(n%i==0)
            n=n/i;
    }
    if(n!=1)  //对应输入的数字本身就是质数
        prime[tol++]=n;
    for(int i=1;i<(1<<tol);i++)  //质因数的组合方法有2的tol次幂个
    {
        int k=1,sum=0;
        for(int j=0;j<tol;j++)
        {
            if(i&(1<<j))    //求一个具体的质因数组合,使用按位与方法
            {
                k=k*prime[j];
                sum++;
            }
        }
        cnt[k]++;
        num[k]=sum;
    }
}
int main()
{
    int m,n;
    long long i;
    for(i=1;i<10010;i++)
        p[i]=i*(i-1)*(i-2)*(i-3)/24;
    while(cin>>n)
    {
        memset(cnt,0,sizeof(cnt));
        for(i=0;i<n;i++)
        {
            cin>>m;
            solve(m);
        }
        long long ans=0;
        for(i=0;i<10010;i++)
        {
            if(cnt[i]>=4)
            {
                if(num[i]&1) 
                    ans = ans+p[cnt[i]];
                else
                    ans = ans-p[cnt[i]];
            }
        }
        cout<<p[n]-ans<<endl;
    }
    return 0;
}

引自:http://www.voidcn.com/article/p-yddwtjwu-bda.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值