Co-prime
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total
Submission(s): 626 Accepted Submission(s): 234
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}.
题意:
给定一个区间(a,b),求解与n其中有多少个数字和n互质
题解:
若a=1,b=13,n=6
第一步:求出n的质因子:2,3
第二步:(1,13)中是n的因子的倍数当然就不互质了(2,4,6,8,10)->n/2 6个,(3,6,9,12)->n/3 4个,(5,10)->n/5 2个
第三步:这里就需要用到容斥原理了,公式就是:n/2+n/3+n/5-n/(2*3)-n/(2*5)-n/(3*5)+n/(2*3*5).
第四步:13减去上叙式子的值
求解质因子:
void devide(LL n)//求一个数的质因子
{
tot=0;
for(LL i=2;i*i<=n;i++){
if(n%i==0){
a[tot++]=i;
while(n%i==0)
n=n/i;
}
}
if(n>1)//这里要记得
a[tot++]=n;
}
下面有两种方法,主要的思想都是枚举子集
方法一:队列:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
LL a[1000],tot;
void devide(LL n)//求一个数的质因子
{
tot=0;
for(LL i=2;i*i<=n;i++){
if(n%i==0){
a[tot++]=i;
while(n%i==0)
n=n/i;
}
}
if(n>1)//这里要记得
a[tot++]=n;
}
LL deal(LL m)//用队列数组实现容斥原理
{
LL que[10000],pos=0,sum=0;
que[pos++]=-1;
for(LL i=0;i<tot;i++){
LL k=pos;
for(LL j=0;j<k;j++)
que[pos++]=que[j]*a[i]*(-1);
}
for(LL i=1;i<pos;i++)
sum=sum+m/que[i];
return sum;
}
int main()
{
int T;
LL a,b,n;
int cases=1;
scanf("%d",&T);
while(T--){
scanf("%I64d%I64d%I64d",&a,&b,&n);
devide(n);
LL sum=b-deal(b)-(a-1-deal(a-1));
printf("Case #%d: %I64d\n",cases++,sum);
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
LL a[1000],tot;
void devide(LL n)//求一个数的质因子
{
tot=0;
for(LL i=2;i*i<=n;i++){
if(n%i==0){
a[tot++]=i;
while(n%i==0)
n=n/i;
}
}
if(n>1)//这里要记得
a[tot++]=n;
}
LL deal(LL x)
{
LL ans=0;
for(LL i=1;i<(1LL<<tot);i++)
{
int sum=0,temp=1;
for(int j=0;j<tot;j++)
{
if(i&(1LL<<j)){
sum++;
temp*=a[j];
}
}
if(sum&1)
ans+=x/temp;
else
ans-=x/temp;
}
return ans;
}
int main()
{
int T;
LL a,b,n;
int cases=1;
scanf("%d",&T);
while(T--){
scanf("%I64d%I64d%I64d",&a,&b,&n);
devide(n);
LL sum=b-deal(b)-(a-1-deal(a-1));
printf("Case #%d: %I64d\n",cases++,sum);
}
return 0;
}