博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU2588--GCD(欧拉函数)
阅读量:4687 次
发布时间:2019-06-09

本文共 2422 字,大约阅读时间需要 8 分钟。

Problem 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.

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

31 110 210000 72

Sample Output

16260

Source

ECJTU 2009 Spring Contest

Recommend

lcy

题意:

题目意思很简单,在X∈[1~N],存在多少个X使得GCD(X,N)>=M,统计X符合要求的个数。

如果直接暴力遍历N次,每次操作的复杂度高达10^9,肯定会超时的。常规的方法肯定不行。

①首先,补充一下关于GCD()的一些基础知识。

  1,如果GCD(a,b)=c,则可以知道GCD(a/c,b/c)=1;(  GCD(a,b)=c  <=>  GCD(a/c,b/c)=1  )

  2,设GCD(a,b)=c,如果想要GCD(a,b*d)=c,用①_1可知,

    只需满足GCD(a/c,(b/c)*d)=1即可(这个限制既为,满足最大公约数的要求).

②然后,我们所要求的是GCD(X,N)>=M,也就是说我们要求一个GCD(X,N)=Z,的数,

  1,如果M==1,则可以知道在[1,N]中任意数X的GCD(X,N)>=1,所以符合要求的个数为N。

  2,如果M>1,则这个X一定是N的约数(大于1),或者是约数(大于1)的倍数 <--------- (只有如此,才能使得GCD(X,N)!= 1)

③再者,我们需要统计的数符合要求的X的个数呢?

  1,正如②_2可以知道GCD(N,X)=X,能够使得GCD()=X的数有约数(大于1)及约数的倍数两部分组成,记这个约数为X,则GCD(N,X*q)=X     (q>=1)

  只需要计算1~N中有多少个(X*q)即可。

  2,由①_2可知,要使得GCD(N,X*q)=X,需要满足GCD(N/X,q)=1.也就是统计1~N/X中有多少个数与N/X互质。

求1~N中,有多少个与N互质的数,欧拉函数,SUM+=Eular(N/X);

④最后,如何不重复的统计其公约数为符合条件X的数呢?

只要X不相同,且满足③_2条件,qX就不会相同。

简单证明:

设有N的两个约数a,b 且a<=b, 若有q1*a=q2*b,则gcd(N/a, q1*b)= b或b的倍数 != 1     <-----------------  N/a含有因子b,而q1*b也有因子b

 

参考博客:

代码:

#include 
#include
#include
using namespace std;int Eular(int N){ int sign=1,i; for(i=2;i*i<=N;i++) { if(N%i==0) { N/=i;sign*=i-1; while(N%i==0) {N/=i;sign*=i;} } } if(N>1) sign*=N-1; return sign;}int main(){ int A,B,T,i,sign; scanf("%d",&T); while(T--) { scanf("%d%d",&A,&B); for(i=1,sign=0;i*i<=A;i++)/*分解约数*/ if(A%i==0) /*分解约数,同时判断两边*/ { /*如果为平方数则主需要判断一次*/ if(i>=B) sign+=Eular(A/i); if((A/i)!=i&&(A/i)>=B)/*判断是否为平方数*/ sign+=Eular(i); } printf("%d\n",sign);/*输出答案*/ } return 0;}

转载于:https://www.cnblogs.com/liuzhanshan/p/6287897.html

你可能感兴趣的文章
js 回到頂部
查看>>
$ is not defined与SpringMVC访问静态资源
查看>>
第五周作业
查看>>
iphone中扫描wifi热点
查看>>
JavaScript中Array类型方法总结
查看>>
关于<input type="hidden"/>标签的记录
查看>>
C++ 类 & 对象
查看>>
ASP.NET Core 运行原理解剖[2]:Hosting补充之配置介绍
查看>>
007-JQuery 筛选
查看>>
部署java项目到阿里云服务器(centos7版本)
查看>>
scala文件通过本地命令运行
查看>>
UE中使用正则表达式的一些技巧
查看>>
Java中的并发工具类
查看>>
JSONObject与JSONArray的使用
查看>>
Android适应方案汇总(三)
查看>>
bootstrap table 服务器端分页--ashx+ajax
查看>>
JavaMaven【三、常用指令】
查看>>
一个有趣的.net程序死锁问题
查看>>
PTA-1015——Reversible Primes
查看>>
方法的重写
查看>>