和1695题类似的题目,不过简单点.求区间[A,B]里和N互质的数的个数,那么可以通过容斥原理求出[1, r] 区间里和N互质的数的个数.
容斥原理的方法和1695题的方法类似,这里给上链接1695.
答案自然就是[1, B] - [1, A].
#include <memory.h>
#include <cstdio>
#include <vector>
using namespace std;
const int MAX = 1000001;
int prime[MAX / 10], prime_idx;
bool is_prime[MAX];
void init_prime(){
memset(is_prime + 2, true, sizeof(is_prime));
for (int i = 2; i < MAX; ++i)
{
if(is_prime[i]){
prime[prime_idx++] = i;
for(int j = i + i; j < MAX; j += i){
is_prime[j] = false;
}
}
}
}
long long inclusion_exclusion(long long r, long long n){
long long res = 0, tn = n;
vector<int> p;
for(int i = 0; i < prime_idx && prime[i] < tn; ++i){
if(tn % prime[i] == 0){
p.push_back(prime[i]);
while(tn % prime[i] == 0){
tn /= prime[i];
}
}
}
if(tn > 1){
p.push_back(tn);
}
for(int i = 1; i < (1 << p.size()); ++i){
long long bits = 0, multiple = 1;
for(int j = 0; j < p.size(); ++j){
if(i & (1 << j)){
bits++;
multiple *= p[j];
}
}
if(bits & 1)res += r / multiple;
else res -= r / multiple;
}
return r - res;
}
int main(){
init_prime();
int T, caseno = 1;
scanf("%d", &T);
while(T--){
long long A, B, N;
scanf("%I64d%I64d%I64d", &A, &B, &N);
printf("Case #%d: %I64d\n", caseno++, inclusion_exclusion(B, N) - inclusion_exclusion(A - 1, N));
}
return 0;
}