Description
给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。
两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的。 Input 第一行输入一个整数T(1 <= T <= 100),表示T组测试数据。 接下来T行,每行3个整数a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔开。 Output 输出一个整数表示和n互质的数的个数。
Sample Input2
1 10 2
3 10 5Sample Output
5 6
感觉自己讲不清楚,引用一下NJUST comzyh的题解吧,总而言之就是分解+容斥原理
容斥原理、先对n分解质因数,分别记录每个质因数,那么所求区间内与某个质因数不互质的个数就是n/r(i),假设r(i)是r的某个质因子 假设只有三个质因子,总的不互质的个数应该为p1+p2+p3-p1p2-p1p3-p2p3+p1p2*p3, 及容斥原理,pi代表n/r(i),即与某个质因子不互质的数的个数,当有更多个质因子的时候,可以用状态压缩解决,二进制位上是1表示这个质因子被取进去了。如果有奇数个1就相加,反之则相减。
C++ Code
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <bitset>
using namespace std;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-6;
const int MAX=2*1e5+10;
long long prime[MAX];
long long sprime[MAX];
bitset<MAX> pri;
long long k,cnt;
void is_prime() {
pri.set();
for(long long i=2; i<MAX; i++) {
if(pri[i]) {
prime[k++]=i;
for(long long j=i+i; j<MAX; j+=i)
pri[j]=0;
}
}
}
void Divide(long long n) {
cnt=0;
long long t=(long long)sqrt(1.0*n);
for(long long i=0; prime[i]<=t; i++) {
if(n%prime[i]==0) {
sprime[cnt++]=prime[i];
while(n%prime[i]==0)
n/=prime[i];
}
}
if(n>1)
sprime[cnt++]=n;
}
long long Ex(long long n) {
long long q[MAX];
long long sum=0;
long long t=1;
q[0]=-1;
for(long long i=0; i<cnt; i++) {
long long x=t;
for(long long j=0; j<x; j++) {
q[t]=q[j]*sprime[i]*(-1);
t++;
}
}
for(long long i=1; i<t; i++)
sum+=n/q[i];
return sum;
}
int main() {
int T;
int icase=1;
long long A,B,N;
long long res;
is_prime();
cin>>T;
while(T--) {
cin>>A>>B>>N;
Divide(N);
res=(B-Ex(B))-(A-1-Ex(A-1));
cout<<res<<endl;
}
return 0;
}