HDOJ 4135 Co-prime(容斥原理)

来源:互联网 发布:淘宝代购only是正品吗 编辑:程序博客网 时间:2024/05/20 18:52

Co-prime

Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4645    Accepted Submission(s): 1854

Problem Description

Given a number N, you areasked to count the number of integers between A and B inclusive which arerelatively prime to N.
Two integers are said to be co-prime or relatively prime if they have no commonpositive divisors other than 1 or, equivalently, if their greatest commondivisor is 1. The number 1 is relatively prime to every integer.

 

 

Input

The first line on inputcontains T (0 < T <= 100) the number of test cases, each of the next Tlines contains three integers A, B, N where (1 <= A <= B <= 1015)and (1 <=N <= 109).

 

 

Output

For each test case, print thenumber of integers between A and B inclusive which are relatively prime to N.Follow the output format below.

 

 

Sample Input

2

1 10 2

3 15 5

 

 

Sample Output

Case #1: 5

Case #2: 10

 

Hint

In the first test case, thefive integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.




考查知识点为容斥原理。

先大致介绍下容斥原理:主要作用是实现没有重复没有遗漏地计数。

方法:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去

例如:对于三个集合的话就是|A∪B∪C| = |A|+|B|+|C| - |A∩B| - |B∩C| - |C∩A| + |A∩B∩C|

易得出现的元素个数是奇数就加,偶数就减

#include <bits/stdc++.h>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(ll i=(a);i<(b);++i)const int maxn = 3000005;const int mod = 200907;#define ll long long#define rush() int T;scanf("%d",&T);while(T--)ll a,b,n;int m;ll prime[70];void getprime()     //求出 n 的质因子{    m=0;    for(ll i=2;i*i<=n;i++)    {        if(n&&n%i==0)        {            prime[m++]=i;            while(n&&n%i==0)                n/=i;        }    }    if(n>1)        prime[m++]=n;}ll solve(ll num)    //返回1~num中与n不互素的数的个数{    ll ans=0,temp;    int flag;    for(ll i=1;i<(ll)(1<<m);i++)   //用二进制来表示所取互质数的组合    {        temp=1;        flag=0;        f(j,0,m)        {            if(i&(ll)(1<<j))   //判断取了哪几个互质数            {                flag++;                temp*=prime[j];            }        }        if(flag&1)                ans+=num/temp;            else ans-=num/temp;    }    return ans;}int main(){    int t=1;    rush()    {        scanf("%I64d%I64d%I64d",&a,&b,&n);        getprime();        ll ans=(b-solve(b))-(a-1-solve(a-1));        printf("Case #%d: %I64d\n",t++,ans);    }    return 0;}



0 0