【题目】
Co-primeTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8210 Accepted Submission(s): 3274 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.
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}. |
【题意】
给定 t 组数据,给定区间 [a,b] 和 k,输出区间 [a,b] 中与 k 互质的数的个数。
【思路】
首先,把问题转化成[1,b]中与k互质的个数-[1,a]中与k互质的个数。要求[1,n]中与k互质的数有多少,我们可以先求[1,n]中与k不互质的数有多少。
这点求法再拉出来细说:先把 k 分解质因数,存在一个数组中。
举个例子,比如 k 的质因子有 2,3,5。那么2、3、5的倍数都不和 k 互质,另外可能有重复的地方,比如6既是2的倍数又是3的倍数,前面用 k/2 + k/3 的时候多减了,这个时候要加上 k / (2*3)。同理,10,15这一类数都应该加上。但是还有类似于30这样的数,它是2,3,5的倍数,减的时候又多减了。
然后我们会发现,出现奇数个数就用加法,偶数个数用减法。
最后的式子是这样的:k / 2 + k / 3 + k / 5 - k / (2 * 3) - k / (3 * 5) - k / (2 * 5) + k / (2 * 3 * 5)。
【代码】
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <map>
#include <set>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define Pi acos(-1)
#define eps 1e-8
using namespace std;
typedef long long int ll;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll fac[1005],num,ansa,ansb,a,b,k;
void init()
{
ansa=0,ansb=0,num=0;
scanf("%lld%lld%lld",&a,&b,&k);
a--;
for(ll i=2;i*i<=k;i++)
{
if(k%i==0) fac[num++]=i;
while(k%i==0) k/=i;
}
if(k>1) fac[num++]=k;
}
ll gcd(ll a, ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a, ll b){return a*b/gcd(a, b);}
void dfs(ll pre,ll now,ll step)
{
if(step>num) return;
ll Lcm=lcm(now,fac[pre]);
if(step&1)
{
ansa+=a/Lcm;
ansb+=b/Lcm;
}
else
{
ansa-=a/Lcm;
ansb-=b/Lcm;
}
for(ll i=pre+1;i<num;i++)
dfs(i,Lcm,step+1);
}
main()
{
int t; scanf("%d",&t);
for(int i=1;i<=t;i++)
{
init();
for(int j=0;j<num;j++)
dfs(j,fac[j],1);
ll ans=(b-a)-(ansb-ansa);
printf("Case #%d: %lld\n",i,ans);
}
}