Time Limit: 1000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64d |
Description
The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.
Input
The first line of input is an integer T(T<=100) representing the number of test cases. The following T lines each contains two numbers N and M (2<=N<=1000000000, 1<=M<=N), representing a test case.
Output
For each test case,output the answer on a single line.
Sample Input
3 1 1 10 2 10000 72
Sample Output
1 6 260
解决方案:设X,N的公约数为d,有X=p*d,N=b*d;那么p,b都与d互素,那么问题就成了求小于d的数内,与d互质的数的个数,这个问题就交给欧拉函数了。
欧拉函数:Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。euler(1)=1(唯一和1互质的数就是1本身)。
求法1:
int eul(int x){
int res=x,X=x;
for(int i=2;i*i<=X;i++){
if(X%i==0) res=res/i*(i-1);
while(X%i==0) X/=i;
}
if(X>1) res=res/X*(X-1);
return res;
}
求法2(打表):
void init()
{
for(int i=1; i<MMAX; i++)
euler[i]=i;
for(int i=2; i<MMAX; i++)
if(euler[i]==i)
{
for(int j=i; j<MMAX; j+=i)
euler[j]=euler[j]/i*(i-1);///先除,再乘是为了防止中间数溢出
}
}
code:
#include<iostream>
#include<cstdio>
#define MMAX 1000000
using namespace std;
int euler[MMAX];
/*void init()
{
for(int i=1; i<MMAX; i++)
euler[i]=i;
for(int i=2; i<MMAX; i++)
if(euler[i]==i)
{
for(int j=i; j<MMAX; j+=i)
euler[j]=euler[j]/i*(i-1);///先除,再乘是为了防止中间数溢出
}
}*欧拉函数打表法
int eul(int x){
int res=x,X=x;
for(int i=2;i*i<=X;i++){
if(X%i==0) res=res/i*(i-1);
while(X%i==0) X/=i;
}
if(X>1) res=res/X*(X-1);
return res;
}
int main()
{
int t,N,M;
// init();
scanf("%d",&t);
while(t--){
int sum=0;
scanf("%d%d",&N,&M);
for(int i=1;i*i<=N;i++){
if(N%i==0){
if(i>=M)
sum+=eul(N/i);
if((N/i)!=i&&(N/i)>=M)
sum+=eul(i);
}
}
cout<<sum<<endl;
}
return 0;
}