HDU 4135 Co-prime(容斥定理)

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


 

Problem Description

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

 

Input

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

 

Output

For each test case, print the number 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, the five integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.

PS:这个题如果用暴力直接跑a,b。肯定会超时的,所以这里我们可以用到容斥定理,我们求a,b里与n互质的个数,可以求这个范围内与n不互质的数的个数,再用总个数减去这个个数,就是答案。首先我们算1~b里与n不互质的个数,再算1~a里与n不互质的个数。两数相减,就是a~b中与n不互质的个数了。

举一组实例吧:假设m=12,n=30.。

第一步:求出n的质因子:2,3,5;

第二步:(1,m)中是n的因子的倍数当然就不互质了(2,4,6,8,10)=n/2  6个,(3,6,9,12)=n/3  4个,(5,10)=n/5  2个。6+4+2=12个了,里面明显出现了重复的,我们现在要处理的就是如何去掉那些重复的了!

第三步:这里就需要用到容斥原理了,公式就是:n/2+n/3+n/5-n/(2*3)-n/(2*5)-n/(3*5)+n/(2*3*5).

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<cmath>
const int maxn=1e4+10;
const int mod=1e9+7;
const int inf=1e9+10;
#define me(a,b) memset(a,b,sizeof(a))
#define PI 3.1415926
#define e exp(1.0)
typedef long long ll;
using namespace std;
ll a[500],l;
void ola(ll n)
{
    l=0;
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
            a[l++]=i;///n的因子
        while(n%i==0)
            n/=i;
    }
    if(n>1)
        a[l++]=n;
}
ll paici(ll m)
{
    ll temp[maxn],t=0,sum=0;me(temp,0);
    temp[t++]=-1;
    for(int i=0;i<l;i++)
    {
        int k=t;
        for(int j=0;j<k;j++)
            temp[t++]=temp[j]*a[i]*(-1);///这步可以自己单步调试下,应该就能理解。
    }
    for(int i=1;i<t;i++)
        sum+=m/temp[i];
    return sum;
}
int main()
{
   int t,Case=1;cin>>t;
   while(t--)
   {
       ll a,b,n;cin>>a>>b>>n;
       ola(n);///找因子
       ll s=b-paici(b)-(a-1-paici(a-1));
       cout<<"Case #"<<Case++<<": "<<s<<endl;

   }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41292370/article/details/81431339
今日推荐