【数论】HDU4135:Co-prime

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 <= 10 15) and (1 <=N <= 10 9).
 

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],从区间[a,b]中找出共有多少个数是与n互质的。

思路:

欧拉函数得到的是小于n与n互质的个数,这里是个区间。由于区间较大,不可能对[a,b]进行遍历,

考虑计算区间[1,a-1]中与n互质的个数num1,[1,b]中与n互质的个数num2,最终结果就是两者

相减的结果。

现在考虑如何计算区间[1,m]中n互质的个数num,num等于 (m - 与n不互质的个数)。

与n不互质的数就是[1,m]中n的素因子的倍数。

例如m = 12,n = 30的情况。

30的素因子数为2、3、5。

[1,12]中含有2的倍数的有:(2、4、6、8、10、12) = n/2 = 6个

[1,12]中含有3的倍数的有:(3、6、9、12) = n/3 = 4个

[1,12]中含有5的倍数的有:(5、10) = n/5 = 2个

与n不互质的数个数就是上边三个集合取并集的部分。这里用到了容斥定理,我用的增长的队列数组

来实现容斥定理,具体参考代码。

 1 #include <iostream>
 2 #include <cstdio>
 3 #define ll __int64
 4 using namespace std;
 5 const int maxn = 1e5+50;
 6 ll factor[105],s[maxn],num;
 7 void getphi(ll x){
 8     num = 0;
 9     for(ll i = 2; i*i <= x; i++)
10     {
11         if(x % i == 0)
12         {
13             while(x % i == 0)
14             {
15                 x /= i;
16             }
17             factor[num++]=i;
18         }
19     }
20     if(x != 1)
21         factor[num++]=x;
22 
23 }
24 ll solve(ll n)
25 {
26     ll k,cnt,ans;
27     cnt=ans=0;
28     s[cnt++]=-1;
29     for(ll i=0;i<num;i++)
30     {
31         k=cnt;
32         for(ll j=0;j<k;j++)
33         {
34             s[cnt++]=-1*s[j]*factor[i];
35         }
36     }
37     for(ll i=1;i<cnt;i++)
38     {
39         ans+=n/s[i];
40     }
41     return ans;
42 }
43 int main()
44 {
45     int T;
46     scanf("%d",&T);
47     for(int i=1;i<=T;i++)
48     {
49         ll x,y,n;
50         scanf("%I64d%I64d%I64d",&x,&y,&n);
51         getphi(n);
52         ll a=y-solve(y);
53         ll b=x-1-solve(x-1);
54         ll ans=a-b;
55         printf("Case #%d: %I64d
",i,ans);
56     }
57 
58     return 0;
59 }
View Code
 
原文地址:https://www.cnblogs.com/SoulSecret/p/8432278.html