Co-prime
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1544 Accepted Submission(s): 592
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.
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 <= 10
15) and (1 <=N <= 10
9).
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: 10HintIn the first test case, the five integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.
如果一个个的判断是否互素 会超时
我们考虑相反的问题 求不与n互素的个数 即这些数与n有相同的数因子
考虑n所有的素因子pi 求在[a,b]范围内有多少个能被pi整除
如果全部把这些数全都减去 会减多了 因为一个数会是几个素因子的公倍数
所以用容斥原理
用欧拉函数处理出 n所有的素因子
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100100
#define INF 0x7fffffff
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
ll pri[1000000];
int num;
void phi(ll n)
{
num=0;
for(int i=2;i*i<=n;i++)
{
if(n&&n%i==0)
{
while(n%i==0)
{
n/=i;
}
pri[num++]=i;
}
}
if(n>1) pri[num++]=n;
}
ll ans(ll n,int m)
{
ll res=0;
ll y=(ll)1<<m;//用二进制来1,0来表示第几个素因子是否被用到,如m=3,三个因子是2,3,5,则i=3时二进制是011,表示第2、3个因子被用到
for(int i=1;i<y;i++)
{
int flag=0;
ll tmp=1;
for(int j=0;j<m;j++)
{
if(i&(ll)(1<<j))//判断第几个因子目前被用到
{
flag++;//记录用的因子个数
tmp*=pri[j];
}
}
if(flag&1)
res+=n/tmp;
else res-=n/tmp;
}
return res;
}
int main()
{
//freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
int cs=1;
while(tc--)
{
ll a,b,n;
scanf("%I64d%I64d%I64d",&a,&b,&n);
phi(n);
// for(int i=0;i<num;i++)
// cout<<pri[i]<<endl;
printf("Case #%d: %I64d\n",cs++,(b-ans(b,num))-(a-1-ans(a-1,num)));
}
return 0;
}