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.
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
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 }