gcd & lcm
2015-09-27 22:33
253 查看
欧几里得算法计算两数最大公约数和最小公倍数是常遇到的问题。现在写几个问题来回顾一下它的应用。
hdu 1222 wolf and rabbit (gcd)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1222
大意:给定长度n,wolf从0开始捕捉兔子,下一点是k%n,再下一点是2k%n,3k%n……问,有没有点是wolf不能访问到的。
可以发现,只有wolf一次移动的距离和总的长度的最大公约数是1,所有的点才都能被遍历。
poj 2773 Happy 2006
题目:http://poj.org/problem?id=2773
大意:给定m,求出第k个和m互质的数字。
由于m (1 <= m <= 1000000), K (1 <= K <= 100000000),所以求出第k个互质数字要考虑到一种压缩方法,不要一个一个的暴力判断。
【曾经的思路:对于k的判断,可以用欧拉函数断定其范围,如果kth primer[k<=phi(m)]在m之内,则可以用fac[k]直接输出[m内,可以用素因子排除不互质的数字]。超出m的范围则直接用gcd() 或 素因子判断即可。但是这样TLE了。想用euler数组加二分,但是MLE。-_-怎么办?】
欧几里得算法含有的信息:gcd(b×t+a,b)=gcd(a,b) (t为任意整数)
则如果a与b互素,则b×t+a与b也一定互素,如果a与b不互素,则b×t+a与b也一定不互素,故与m互素的数对m取模具有周期性。由此一来就可解决K较大时的情况。得到的信息:设m范围内的素数有k个,数字n对应至少有互质数n/m*k。当n是k的倍数时,对应的互质数:m*(n/k-1)+fac[k]. 当其不是倍数关系:n/k*m+fac[n%k]
zoj 1577 GCD & LCM
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1577
GCD & LCM
Time Limit: 2 Seconds
Memory Limit: 65536 KB
Given x and y (2 <= x <= 100,000, 2 <= y <= 1,000,000), you are to count the number of p and q such that:
1) p and q are positive integers;
2) GCD(p, q) = x;
3) LCM(p, q) = y.
Input
x and y, one line for each test.
Output
Number of pairs of p and q.
Sample Input
3 60
Sample Output
4
分析:GCD(p, q) = x; --> GCD(p/x,q/x)=1;
LCM(p, q) = y. --> LCM(p/x,q/x)=(p*q/x^2)/gcd(p/x,q/x)=p*q/x^2=y/x
设p/x,q/x分别是t1,t2. 有gcd(t1,t2)=1; t1*t2=y/x=w 现在问题转换成寻找有多少对t1,t2互质且乘积就是w.
于是对w素因子分解,设w对应的因子展开式是(1+q1+q1^2+……+q1^n1)(1+q2+q2^2+……+q2^n2)……(1+qk+qk^2+……+qk^nk),那么互质的两个乘积因子情况:qi^ni的组合数,即C(n,0)+C(n,1)+C(n,2)+……+C(n,n)=2^n。【不可能是qi^nj,其中0<nj<ni,那样的话就不互质了】
http://acm.hdu.edu.cn/showproblem.php?pid=1019
分析:单纯的求多个数字的最大公倍数。对的,没有别的陷阱。
hdu 1222 wolf and rabbit (gcd)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1222
大意:给定长度n,wolf从0开始捕捉兔子,下一点是k%n,再下一点是2k%n,3k%n……问,有没有点是wolf不能访问到的。
可以发现,只有wolf一次移动的距离和总的长度的最大公约数是1,所有的点才都能被遍历。
#include <iostream> #include <cstdio> #define LL long long using namespace std; LL gcd(LL a, LL b){ return b?gcd(b,a%b):a; } int main() { LL T,m,n; while(cin>>T){ while(T--){ LL f; scanf("%lld%lld",&m,&n); if(gcd(m,n)==1){ printf("NO\n"); } else printf("YES\n"); } } return 0; }
poj 2773 Happy 2006
题目:http://poj.org/problem?id=2773
大意:给定m,求出第k个和m互质的数字。
由于m (1 <= m <= 1000000), K (1 <= K <= 100000000),所以求出第k个互质数字要考虑到一种压缩方法,不要一个一个的暴力判断。
【曾经的思路:对于k的判断,可以用欧拉函数断定其范围,如果kth primer[k<=phi(m)]在m之内,则可以用fac[k]直接输出[m内,可以用素因子排除不互质的数字]。超出m的范围则直接用gcd() 或 素因子判断即可。但是这样TLE了。想用euler数组加二分,但是MLE。-_-怎么办?】
欧几里得算法含有的信息:gcd(b×t+a,b)=gcd(a,b) (t为任意整数)
则如果a与b互素,则b×t+a与b也一定互素,如果a与b不互素,则b×t+a与b也一定不互素,故与m互素的数对m取模具有周期性。由此一来就可解决K较大时的情况。得到的信息:设m范围内的素数有k个,数字n对应至少有互质数n/m*k。当n是k的倍数时,对应的互质数:m*(n/k-1)+fac[k]. 当其不是倍数关系:n/k*m+fac[n%k]
#include <iostream> #include <cstdio> using namespace std; typedef long long LL; const int maxn=1e6+5; int gcd(int a,int b){ return b?gcd(b,a%b):a; } int fac[maxn],top; int main(){ int m,n; while(cin>>m>>n){ top=0; for(int i=1;i<=m;i++){ //m可能等于1.所以要写<= if(gcd(m,i)==1) fac[++top]=i; } LL ans; if(n%top==0) ans=m*(n/top-1)+fac[top]; else ans=m*(n/top)+fac[n%top]; printf("%lld\n",ans); } return 0; }
zoj 1577 GCD & LCM
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1577
GCD & LCM
Time Limit: 2 Seconds
Memory Limit: 65536 KB
Given x and y (2 <= x <= 100,000, 2 <= y <= 1,000,000), you are to count the number of p and q such that:
1) p and q are positive integers;
2) GCD(p, q) = x;
3) LCM(p, q) = y.
Input
x and y, one line for each test.
Output
Number of pairs of p and q.
Sample Input
3 60
Sample Output
4
分析:GCD(p, q) = x; --> GCD(p/x,q/x)=1;
LCM(p, q) = y. --> LCM(p/x,q/x)=(p*q/x^2)/gcd(p/x,q/x)=p*q/x^2=y/x
设p/x,q/x分别是t1,t2. 有gcd(t1,t2)=1; t1*t2=y/x=w 现在问题转换成寻找有多少对t1,t2互质且乘积就是w.
于是对w素因子分解,设w对应的因子展开式是(1+q1+q1^2+……+q1^n1)(1+q2+q2^2+……+q2^n2)……(1+qk+qk^2+……+qk^nk),那么互质的两个乘积因子情况:qi^ni的组合数,即C(n,0)+C(n,1)+C(n,2)+……+C(n,n)=2^n。【不可能是qi^nj,其中0<nj<ni,那样的话就不互质了】
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int fac[1010],top; void resolve(int a){ top=0; for(int i=2;i*i<=a;i++){ if(a%i==0){ fac[top++]=i; while(a%i==0) a/=i; } } if(a>1) fac[top++]=a; } int power(int p){ int ans=1,temp=2; while(p){ if(p&1) ans=ans*temp; temp=temp*temp; p>>=1; } return ans; } int main() { int x,y; while(cin>>x>>y){ if(y%x){ printf("0\n"); continue; } int w=y/x; resolve(w); printf("%d\n",power(top)); } return 0; }hdu 1019 Least Common Multiple
http://acm.hdu.edu.cn/showproblem.php?pid=1019
分析:单纯的求多个数字的最大公倍数。对的,没有别的陷阱。
#include <iostream> #include <cstdio> using namespace std; int gcd(int a,int b){ return b?gcd(b,a%b):a; } int a[10000]; int main() { //freopen("cin.txt","r",stdin); int t,m; cin>>t; while(t--){ int g,ans=1; scanf("%d%d",&m,&a[0]); ans=a[0]; for(int i=1;i<m;i++){ scanf("%d",&a[i]); g=gcd(ans,a[i]); ans=ans/g*a[i]; } printf("%d\n",ans); } return 0; }
相关文章推荐
- for循环代替while(1)
- 验证码 mewebstudio/captcha
- 第五周
- 添加view
- LeetCode——Single Number III
- ListActivity的注意点
- idea or android studio 使用
- 黑马程序员——IO流:自顶向下的总结
- Python进阶 - 进程与线程
- javascript 中的apply()和call()方法详解
- jdk5.0新特性
- 百度云分享,以前找到的各种东东,分享给大家···Office软件(全-C)
- Python进阶 - GUI程序设计(tkinter)
- Async和Await进行异步编程
- 归并链表
- Android 中的 Service 全面总结(转载)
- 成果展
- nyoj747蚂蚁的难题(三)&&hdoj5501The Highest Mark【dp】
- 自动化测试必将取代手工测试
- 模式总结(一)——创建型模式(Creational Pattern)