您的位置:首页 > 其它

hdu2588(欧拉函数的应用)

2016-04-06 22:32 309 查看
题意:给定N,M(2<=N<=1000000000, 1<=M<=N), 求1<=X<=N 且gcd(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

思路:因为n太大,用常规方法做肯定超时,这里需要引用欧拉函数。

欧拉函数只能求出小于n且与n互质的所有数的个数,但是无法求出最大公约数是否大于m

但是 我们可以这样想 设a为大于等于m的n的一个约数,那么euler(n/a)表示的就是所有小于a与a互质的数的个数,设任一个数为x,那么这些数再乘以a就有gcd(n,x*a) = a;

所以我们可以想到答案为所有n大于等于m的约数ai的euler(n/ai)之和

但是还有一个问题 这些数是否会重复呢?答案是否定的

设a、b为两个不同的大于等于m的n的约数

假设存在重复 那么就有 a*x = b*y (x是小于等于n/a且与n/a互质的数,y是n/b的。。)

变形 得到 x*n/b = y*n/a 由于x和n/a互质 所以 x是y的约数(因为两边分解质因数的时候n/a不能分出x的约数 只能是y来分)

不妨设 y = kx(k>1) 则 n/b = k(n/a)

由于y和n/b互质 则kx和n/b互质 但是n/b有个k作为约数 所以他们有公约数k 这显然推出k = 1 于是产生a==b矛盾!

所以不会产生重复

代码:

#include<stdio.h>
#include<math.h>
int euler(int n)//求欧拉函数值
{
int temp=n;
int sqrt_n=(int)sqrt(n);
for(int i=2;i<=sqrt_n;i++)
{
if(n%i==0)
temp=temp*(i-1)/i;
while(n%i==0)
{
n=n/i;
}
}
if(n>1)  //这里n有可能是质数或者大于sqrt(n)的质数只能有一个,所以进行判断
temp=temp/n*(n-1);
return temp;
}
int main(void)
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,s=0;
scanf("%d%d",&n,&m);
if(m==1)// 由于下面i是从2开始的,如果m=1,因为因子1也数满足条件的,会判断错误,提前判断输出,
{
printf("%d\n",n);
continue;
}
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
if(n/i>=m)
s=s+euler(i);
if(i>=m)
s=s+euler(n/i);
}
}
if((int)sqrt(n)*(int)sqrt(n)==n&&(int)sqrt(n)>=m)
s=s-euler((int)sqrt(n));
printf("%d\n",s+1);//还有本身n本身也满足条件,
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: