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
思路
关于容斥原理的大体介绍: 容斥原理
题目给出了一个区间[a,b]
和一个数n
,让你求出a~b
中与n
互质的数的个数,首先暴力肯定是会TLE
的,我们考虑一下容斥原理的做法。
要求出从
a
a
到中与
n
n
互质的数的个数,我们只需要求出从1~b
与互质的数的个数减去从1~a
中与
n
n
互质的数的个数,那么问题就转化成了:
已知两个数n,m,求出从1到m中与n互质的数的个数
我们假设n是100,m是20,那么如何求出从1到20中,与100互质的数的个数呢?
首先对100进行质因数分解,结果肯定是2,5
,那么就从这20个数中减去因数存在2的,再减去因数存在5的,再加上因数存在10的(10是2和5的倍数,被计算了两次),也就是:
这就是利用了容斥原理的思想。
所以解决这个题,只需要进行质因数分解,和容斥原理
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
#define inf 1000000
#define mem(a,b) memset(a,b,sizeof(a))
ll a[50],b[1010];//a保存n的质因子,a[0]表示质因子个数
void div(ll n)//分解质因数
{
ll j=0;
for(ll i=2; i*i<=n; i++)
if(n%i==0)
{
while(n%i==0)
n/=i;
a[++j]=i;
}
if(n>1) a[++j]=n;
a[0]=j;
}
ll get_cnt(ll mid)//1--mid之间与n互质的数有多少个
{
ll g=0,sum=mid,t;
b[++g]=1;
for(ll i=1; i<=a[0]; i++)
{
t=g;
for(ll j=1; j<=g; j++)
{
b[++t]=b[j]*a[i]*-1;
sum+=mid/b[t];
}
g=t;
}
return sum;
}
int main()
{
ll t,q=1,a,b,n;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&a,&b,&n);
div(n);
printf("Case #%lld: %lld\n",q++,get_cnt(b)-get_cnt(a-1));
}
return 0;
}