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矛盾!
所以不会产生重复
代码:
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本身也满足条件, } }
相关文章推荐
- Python开发测试工具(二)—Monkey工具的优化
- 详解SQL Server连接(内连接、外连接、交叉连接)
- 复利计算-结对编程
- 每日一题
- 详解linux系统的启动过程及系统初始化
- BAT、网易、蘑菇街面试题整理-7
- Ping测试网络连接状况
- Android开发-简单的图片浏览器
- javascript技术难点(三)之this、new、apply和call详解
- 计算机
- 第七周
- 【Noip模拟By yxj】
- 20135323符运锦----《深入理解计算机系统》第七章知识点总结
- hdoj--5253--连接的管道(最小生成树)
- 【python学习】pip安装及使用
- 产品体验-潮汐
- iOS copy mutableCopy 的实现
- springMVC学习
- shell脚本攻略第二章总结---命令之乐
- 同班同学20年后 身家15亿与月薪5000元的区别