题目
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
题目大意
给出一个数n,求区间[a,b]内与n互质的数的个数。
解题思路
n的质因子的倍数与n不互质。
对于[1,k]范围内的数,可以先算出质因子倍数的个数,然后用总个数k减去质因子倍数的个数就是[1,k]范围内与n互质的数的个数。
这里用到了容斥原理。
代码
#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
using namespace std;
int p[101010],s[101010];
long long f[101010];
bool v[1010100],g[101010];
void work()
{
memset(f,0,sizeof(f));
/*
容斥原理可以用二进制状态压缩实现
例如 1010 表示选了第2个和第四个质数
*/
for (int i=1;i<=(1<<s[0])-1;i++)
{
long long num=1,t=0;
for (int j=0;j<s[0];j++)
if (i&(1<<j))
{
num*=s[j+1];
t++;
}
f[i]=num;
if (t%2==0) g[i]=true;
else g[i]=false;//奇加偶减
}
}
void get_s(long long x)//对n进行质因数分解
{
long long n=x;
for (int i=2;i*i<=n;i++)
{
if (x%i==0)
{
s[++s[0]]=i;
while (x%i==0) x/=i;
}
}
if (x>1) s[++s[0]]=x;
}
long long ask(long long x)
{
long long ans=0;
for (int i=1;i<=(1<<s[0])-1;i++)
if (g[i]) ans-=(x/f[i]);
else ans+=(x/f[i]);//奇加偶减
return x-ans;
}
int main()
{
freopen("k.in","r",stdin);
freopen("k.out","w",stdout);
int T;
cin>>T;
for (int k=1;k<=T;k++)
{
long long a,b,n;
cin>>a>>b>>n;
int t=0;
s[0]=0;
get_s(n);
work();
long long ans=ask(b)-ask(a-1);
cout<<"Case #"<<k<<": "<<ans<<endl;
}
}