Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4384 Accepted Submission(s): 1733
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}.
Source
The Third Lebanese Collegiate Programming Contest
【题目链接】:http://acm.hdu.edu.cn/showproblem.php?pid=4135
【题解】
要求【a..b】这个区间范围内和N互质的数的个数;
可以这样
先求出1..a-1这个范围内和N互质的数的个数A
求出1..b这个范围内和N互质的数的个数B
B-A就是答案了;
求1..X范围内和N互质的数这个问题;
可以转换一下
先求出1..X里面不和N互质的数的个数;
这点
需要先把N质因数分解(几个质数的成绩)一下;
把它的所有质因子处理出来(不用记录具体每个质因子有多少个);
假如N = 6,X = 20
5=2*3
则2的倍数与6都不互质,则ans+=20/2
3的倍数与6都不互质,则ans+=20/3
但是有2和3的公共倍数被重复计算了
则还要减去
即ans-=20/(2*3);
更一般的
我们会发现,出现奇数个数,就用加法,偶数个数用减法。
换一种说法
假设N有num个质因子
则对应二进制有num个数字,每个数字为0或1
把那些为1的位的质因子全部乘上来->temp;
如果1的个数为奇数则ans+X/temp;
否则减去X/temp;
这样就能算出1..X里面不和N互质的数的个数了;
【完整代码】
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;
const int MAXN = 10000;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
LL a,b,n,pri[MAXN];
int num;
LL get_ans(LL x)
{
LL ans = 0;
rep1(i,1,(1<<num)-1)
{
LL y = 1,f = 0;
rep1(j,1,num)
if (i & (1<<(j-1)))
{
y = y*pri[j];
f++;
}
if (f&1)
ans += x/y;
else
ans -= x/y;
}
ans = x-ans;
return ans;
}
int main()
{
//freopen("F:\rush.txt","r",stdin);
int T;
rei(T);
rep1(ii,1,T)
{
num = 0;
rel(a);rel(b);rel(n);
for (LL i = 2;i*i<=n;i++)
if ((n%i)==0)
{
pri[++num] = i;
while ((n%i)==0)
n/=i;
}
if (n > 1)
pri[++num] = n;
printf("Case #%d: %I64d
",ii,get_ans(b)-get_ans(a-1));
}
return 0;
}