Co-prime
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10291 Accepted Submission(s): 4011
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
Recommend
lcy | We have carefully selected several similar problems for you: 1434 3460 1502 4136 4137
题意:
给出a, b, n, 求[a,b]中与n互质的元素个数
思路分析:
乍一看和欧拉函数很像,但是又有点不同。欧拉函数phi[i] = n表示[1,i]中与i互质的个数为n.
因此得想别的办法。
我们要求[a,b]中与n互质的元素个数可以转化成f([a,b]) = f([1,b]) - f([1,a-1]).
那么如何求[1,X]中与n互质的元素个数呢?
我们可以逆着想,求与n不互质的元素个数,这个不互质的元素其实就是n的素因子倍数。假设n的素因子有2,3. 那么2的倍数有[n/2]个,3的倍数有[n/3]个。2和3的倍数里面关于6的倍数被重复加了,需要减掉。这个6就是2,3的最小公倍数。因此不互质元素个数为 [n/2] + [n/3] - [n/lcm(2,3)]。以上就是容斥定理,不再多介绍了。容斥定理遵循一个原则:奇加偶减。
通过容斥定理求出[1,X]不互质的个数,用X减去,就可以得到[1,X]的互质个数了。
下面上代码
#include <iostream>
#include <cstring>
#include <cmath>
#include <map>
#define ll long long
using namespace std;
const int N = 100000;
ll prime[N];
int t;
int vis[N];
ll T, n, a, b;
ll factor[100]; //存放素因子
ll cnt;
ll tmp1, tmp2, ans; //tmp1为[1,a-1]中与n不互质的个数,tmp2为[1,b]中与n不互质的个数
ll gcd(ll a,ll b){
return b == 0?a:gcd(b,a%b);
}
void isPrime() //打素数表
{
t=0;
memset(vis,0,sizeof(vis));
memset(prime,0,sizeof(prime));
for(ll i=2;i<N;i++)
{
if(!vis[i])
{
prime[t++]=i;
for(ll j=i*i;j<N;j+=i)
vis[j]=1;
}
}
}
void splitPrime(ll x) //分解素因子
{
cnt=0;
ll t=x;
for(int i=0;prime[i]<=t/prime[i];i++)
{
while(t%prime[i]==0)
{
factor[cnt]=prime[i];
while(t%prime[i]==0)
{
t/=prime[i];
}
cnt++;
}
}
if(t!=1)
{
factor[cnt]=t;
cnt++;
}
}
void dfs(ll cur, ll lcm, ll id) //求出[1,a-1]和[1,b]与n非互质的个数
{
lcm = factor[cur]*lcm/gcd(lcm,factor[cur]);
// cout<<cur<<" "<<lcm<<endl;
if(id&1) tmp1 += (a-1)/lcm, tmp2 += b/lcm; //读取id最后一个二进制位,若为1,则id为奇数。
else tmp1 -= (a-1)/lcm, tmp2 -= b/lcm;
for(int i = cur+1;i < cnt;i++)
dfs(i, lcm, id+1);
}
int main()
{
isPrime();
cin>>T;
int ii = 1;
while(T--)
{
tmp1 = 0, tmp2 = 0, ans = 0;
cin>>a>>b>>n;
splitPrime(n);
for(int i = 0;i < cnt;i++)
dfs(i,factor[i],1);
ans = (b-tmp2) - (a-1-tmp1); //[1,b]与n互素的个数 - [1,a-1]与n互素的个数就是[a,b]与n互素的个数
printf("Case #%d: %lld\n",ii,ans);
ii++;
}
return 0;
}