hdu 4135 容斥原理

/**
容斥原理
//通常我们求1~n中与n互质的数的个数都是用欧拉函数!
 但如果n比较大或者是求1~m中与n互质的数的个数等等问题,
要想时间效率高的话还是用容斥原理!


先对n分解质因数,分别记录每个质因数,
那么所求区间内与某个质因数不互质的个数就是n / r(i),假设r(i)是r的某个质因子
假设只有三个质因子,
总的不互质的个数应该为p1+p2+p3-p1*p2-p1*p3-p2*p3+p1*p2*p3,
及容斥原理,可以转向百度百科查看相关内容
pi代表n/r(i),即与某个质因子不互质的数的个数
当有更多个质因子的时候,
可以用状态压缩解决,二进制位上是1表示这个质因子被取进去了。
如果有奇数个1,就相加,反之则相减
*/
#include <stdio.h>
#include <math.h>


#define N 16
__int64 pt,pri[N],bit[N]={1};


__int64 ie(__int64 s)
{
    __int64 res = 0,p = 1,cnt = 0;
    for(__int64 i =1;i<bit[pt];++i)
    {
        p = 1;
        cnt = 0;
        for(int j=0;j<pt;++j)
            if(i&bit[j])
            {
                ++cnt;
                p *= pri[j];
            }
        if(cnt&1)
            res += s/p;
        else
            res -= s/p;
    }
    return res;
}
int main()
{
    for(int i = 1;i <= N;++i)
        bit[i] = (bit[i-1]<<1);


    int t,sp = 0;
    __int64 a,b,n;
    scanf("%d",&t);
    while(t--)
    {
        pt = 0;
        int i;
        scanf("%I64d%I64d%I64d",&a,&b,&n);
        for(i = 2;i * i <= n;++i)///对n分解质因数
            if(n && n % i ==0)
            {
                pri[pt++] = i;
                while(n && n%i ==0)
                    n/=i;
            }
        if(n > 1)
            pri[pt++] = n;
        printf("Case #%d: %I64d\n",++sp,b-ie(b)-a+1+ie(a-1));
    }
    return 0;
}
/*
1 10 2
3 15 5
*/


你可能感兴趣的:(hdu 4135 容斥原理)