1. 程式人生 > >題解報告:hdu 4135 Co-prime(容斥定理入門)

題解報告:hdu 4135 Co-prime(容斥定理入門)

分解 容斥 ret amp eve 素因子 nbsp desc 使用

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}. 解題思路:求區間[A,B]與N互質的數的個數,我們可以從其對立面來考慮:分別求區間[1,A-1]、區間[1,B]中與N不互質的數的個數為num1、num2,那麽區間[A,B]與N互質的數的個數就有(B-num2)-(A-1-num1)。怎麽求區間與N不互質的數的個數呢?先分解出N的所有素因子,因為任何一個不小於2的數都能表示成若幹個素數的乘積,然後用其素因子來篩選計算出區間中與N不互質的數的個數即X/p_i(p_i為素因子),這裏要用容斥定理,不重復計數,也沒有遺漏,公式:技術分享圖片
技術分享圖片
AC代碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 int t,cnt,prime[15];LL a,b,n;
 5 LL solve(LL x){//求與n不互質的總個數
 6     int num;LL ans=0,tp;
 7     for(int i=1;i<(1<<cnt);++i){//用二進制來表示每個質因子是否被使用,即有2^cnt-1種可能,此時cnt較小,題目中1e9最多也就8個素因子,二進制優化
 8         tp=1,num=0;
 9         for(int j=0;j<cnt;++j)
10             if(i&(1<<j))num++,tp*=prime[j];//表示選擇哪幾個素因子
11         if(num&1)ans+=x/tp;//奇加
12         else ans-=x/tp;//偶減
13     }
14     return x-ans;
15 }
16 int main(){
17     while(~scanf("%d",&t)){
18         for(int i=1;i<=t;++i){
19             scanf("%lld%lld%lld",&a,&b,&n);cnt=0;
20             for(LL j=2;j*j<=n;++j){//求出n內的所有質因子
21                 if(n%j==0){
22                     prime[cnt++]=j;
23                     while(n%j==0)n/=j;
24                 }
25             }
26             if(n>1)prime[cnt++]=n;
27             printf("Case #%d: %lld\n",i,solve(b)-solve(a-1));//區間差
28         }
29     }
30     return 0;
31 }

題解報告:hdu 4135 Co-prime(容斥定理入門)