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 <= 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
 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
",i,k);
80         }
81     }
82     return 0;
83 }
原文地址:https://www.cnblogs.com/tom987690183/p/3246197.html