HDU 4135 Co-prime 欧拉+容斥定理

Co-prime

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


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 <= 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
 1 /*

 2 题意:求区间[A,B],与数字N互素的个数。

 3 

 4 转化一下思路:1.求[A,B],转化为

 5               [1,B]中与N互素的个数 

 6               减去

 7               [1,A-1]中与N互素的个数。

 8               这样问题就转化为[1,K]的问题了。

 9     2.求[1,K]中与N互素的个数又转化为 K 减去 [1,K]中与N满足

10       gcd(N,k1)>1的个数。

11       接下来,就要求N的素因子了。为什么是素因子??

12       因为每一个数都能有素因子组成。

13       求素因子的方法和求欧拉的方法是一样的。

14       有两种方法,一种适合于单点求取,数字比较大的时候更好。

15                   一种适合于打表求取,适用数字相对较的情况。

16     3.求解的过程中会遇到重复的问题。

17     举一个例子 m=12,n=30

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

19     第二步:(1,m)中是n的因子的倍数当然就不互质了

20     (2,4,6,8,10)->n/2  6个,(3,6,9,12)->n/3  4个,(5,10)->n/5  2个。

21     如果是粗心的同学就把它们全部加起来就是:6+4+2=12个了,

22     那你就大错特错了,里面明显出现了重复的,

23     我们现在要处理的就是如何去掉那些重复的了!

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

25     第四步:我们该如何实现呢?

26     我在网上看到有几种实现方法:dfs(深搜),队列数组,位运算三种方法都可以!

27     上述公式有一个特点:n除以奇数个数相乘的时候是加,n除以偶数个数相乘的时候是减。

28     我这里就写下用队列数组如何实现吧:我们可以把第一个元素设为-1然后具体看代码如何实现吧!

29 */

30 

31 #include<stdio.h>

32 #include<string.h>

33 #include<stdlib.h>

34 

35 __int64 Que[100001];

36 __int64 f[100],len;

37 void Euler(__int64 n)//求取素因子,保存在f[]

38 {

39     __int64 i;

40     len=0;

41     for(i=2;i*i<=n;i++)

42     {

43         if(n%i==0)

44         {

45             while(n%i==0)

46             n=n/i;

47             f[++len]=i;

48         }

49     }

50     if(n!=1)

51     f[++len]=n;

52 }

53 

54 __int64 Capticy(__int64 num)容斥定理的运用

55 {

56     __int64 i,j,t=0,k,sum=0;

57     Que[t++]=-1;

58     for(i=1;i<=len;i++)

59     {

60         k=t;

61         for(j=0;j<k;j++)

62             Que[t++]=-1*Que[j]*f[i];

63     }

64     for(i=1;i<t;i++)

65     sum=sum+num/Que[i];

66     return sum;

67 }

68 

69 int main()

70 {

71     __int64 T,A,B,N,i,k;

72     while(scanf("%I64d",&T)>0)

73     {

74         for(i=1;i<=T;i++)

75         {

76             scanf("%I64d%I64d%I64d",&A,&B,&N);

77             Euler(N);

78             k=B-Capticy(B)-(A-1-Capticy(A-1));

79             printf("Case #%I64d: %I64d\n",i,k);

80         }

81     }

82     return 0;

83 }

 

你可能感兴趣的:(Prim)