您的位置:首页 > 编程语言

关于数的容斥定理的代码实现

2017-11-30 21:16 141 查看
  前述:其实容斥定理的用法并非自己感悟出来的,还是从大量博客里学习的,感觉这种深邃的思想我学不来,看题目的时候都想不到为什么要那样用,但是容斥定理本身是很简单的,公式我就不再展示了。但是还好因为集合的交集的求法比较困难,使得这方面能用固定代码解决的问题的种类大大减少。其中比较广泛的一个应用就是求1-m里面和n互质的数的个数。思路是用m-所有和n非互质的数的和,那么,和n非互质又有一个说法就是和n有大于1的公共素因子,而属于有某个因子a的数的个数的集合个数就是m/a。这样,问题就转化成了这样几个步骤:1.先求n的所有素因子。2.根据容斥定理求和n非互质的数的个数。3.ans=m-和n非互质的数的个数。那么这里我为啥说是代码实现而不说是模板呢,在dalao的博客里面我发现的写法要么是难懂的位运算,要么不用递归难想,而我选择了最直接也可能是最耗时间的解决方法,就是dfs递归,一开始只是出于试探的心理,后来交了几个题目之后发现并未出现超时的现象,于是就当作一个模板来用了,也做出来不少容斥定理的题目。

  AC代码:(参见题目:HDU-4135 J - Co-prime

  题目大意:让求一个区间里面和n互质的数的个数。

  解题思路:假设为[l,r],那么有可以用1-r满足条件的数的个数1-l-1中满足条件的数的个数。

#include<iostream>

#include<cmath>

#include<cstring>

#include<cstdio>

#include<algorithm>

using namespace std;

long long fac[1100];

long long box[1100];

long long n,m,t;

long long fun;

long long gcd(long long a,long long b){

    return b==0?a:gcd(b,a%b);

}

void getfac(){

    long long i,j;

    long long xx=n;

    m=0;

    for (i=2;i<=sqrt(n);i++){

        if (xx%i==0){

            fac[++m]=i;

            while (xx%i==0){

                xx/=i;

            }

        }

    }

    if (xx>1)fac[++m]=xx;

}

void sfind(long long x,long long y,long long z,long long val){

    long long i,j;

    for (i=x;i<=m;i++){

        box[y]=fac[i];

        if (y==z){

            long long temp=1;

            for (j=1;j<=z;j++){

                temp=temp/gcd(temp,box[j])*box[j];

            }

            fun+=val/temp;

        }

        else sfind(i+1,y+1,z,val);

    }

}

long long solve(long long x){

    long long i,j;

    long long temp=1;

    long long ans=0;

    for (i=1;i<=m;i++){

        fun=0;

        sfind(1,1,i,x);

        ans+=fun*temp;

        temp=-temp;

    }

    return x-ans;

}

int main(){

    long long i,j,k,l,r,total,cas=0;

    scanf("%lld",&t);

    while (t--){

        scanf("%lld%lld%lld",&l,&r,&n);

        getfac();

        long long ans=solve(r)-solve(l-1);

        printf("Case #%lld: %lld\n",++cas,ans);

    }

}

  这个题目其实不是我创造出来这个写法的初始版本,这里改造成了一个函数,可以更为广泛的应用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: