GCD and LCM Aizu - 0005(辗转相除)+GCD LCM Inverse POJ - 2429(java或【Miller Rabin素数測试】+【Pollar Rho整数分解】)
題目:GCD and LCM Aizu - 0005
Write a program which computes the greatest common divisor (GCD) and the least common multiple (LCM) of given a and b.
Input
Input consists of several data sets. Each data set contains a and b separated by a single space in a line. The input terminates with EOF.
Constraints
0 < a, b ≤ 2,000,000,000
LCM(a, b) ≤ 2,000,000,000
The number of data sets ≤ 50
Output
For each data set, print GCD and LCM separated by a single space in a line.
Sample Input
8 6
50000000 30000000
Output for the Sample Input
2 24
10000000 150000000
分析:
求最大公約數和最小公倍數。。。
AC代碼:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; typedef long long ll; ll n,m; ll gcd(ll x,ll y) {return y==0?x:gcd(y,x%y); } int main() {while(~scanf("%lld%lld",&n,&m)){ll a=gcd(n,m);printf("%lld %lld\n",a,n*m/a);}return 0; }題意:
給你兩個數a和b的最大公約數和最小公倍數。求a和b(當中在滿足條件的情況下。使a+b盡量小)
題目: LCM Inverse POJ - 2429
Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a and b. But what about the inverse? That is: given GCD and LCM, finding a and b.
Input
The input contains multiple test cases, each of which contains two positive integers, the GCD and the LCM. You can assume that these two numbers are both less than 2^63.
Output
For each test case, output a and b in ascending order. If there are multiple solutions, output the pair with smallest a + b.
Sample Input
3 60
Sample Output
12 15
分析:
作者顯然高估了讀者的數學修養,我對數論一點都不熟悉,這題光靠前面介紹的一點數論皮毛無從下手,還是看了人家的代碼才知道要用Rabin-Miller強偽素數測試和Pollard r因數分解算法。
基本思路是
(1)、(a / gcd) * (b / gcd) = lcm / gcd ,所以需要分解lcm / gcd 。將其分解為互質的兩個數,如果這兩個數之和最小,那么乘上gcd就是所求的答案。
(2)、但是題目數據太大,需要一個高效的素數檢測算法,所以采用Rabin-Miller強偽素數測試
(3)、然后分解成質因子的n次方之積,從這些n次方中挑選一些作為x,剩下的作為y。枚舉x和y的所有可能,找出最小值。
Rabin-Miller強偽素數測試和Pollard r因數分解算法
AC代碼:
此代碼并非我所寫,我只理解了,由于時間緊迫,若有時間,回來鉆研,這里放AC模板。
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<math.h> #include<algorithm> using namespace std; typedef long long ll; #define MAX_VAL (pow(2.0,60)) //miller_rabbin素性測試 ll mod_mul(ll x,ll y,ll mo) {ll t,T,a,b,c,d,e,f,g,h,v,ans;T = (ll)(sqrt(double(mo)+0.5));t = T*T - mo;a = x / T;b = x % T;c = y / T;d = y % T;e = a*c / T;f = a*c % T;v = ((a*d+b*c)%mo + e*t) % mo;g = v / T;h = v % T;ans = (((f+g)*t%mo + b*d)% mo + h*T)%mo;while(ans < 0)ans += mo;return ans; }ll mod_exp(ll num,ll t,ll mo) {ll ret = 1, temp = num % mo;for(; t; t >>=1,temp=mod_mul(temp,temp,mo))if(t & 1)ret = mod_mul(ret,temp,mo);return ret; }bool miller_rabbin(ll n) {if(n == 2)return true;if(n < 2 || !(n&1))return false;int t = 0;ll a,x,y,u = n-1;while((u & 1) == 0){t++;u >>= 1;}for(int i = 0; i < 50; i++){a = rand() % (n-1)+1;x = mod_exp(a,u,n);for(int j = 0; j < t; j++){y = mod_mul(x,x,n);if(y == 1 && x != 1 && x != n-1)return false;x = y;}if(x != 1)return false;}return true; } //PollarRho大整數因子分解 ll minFactor; ll gcd(ll a,ll b) {if(b == 0)return a;return gcd(b, a % b); }ll PollarRho(ll n, int c) {int i = 1;srand(time(NULL));ll x = rand() % n;ll y = x;int k = 2;while(true){i++;x = (mod_exp(x,2,n) + c) % n;ll d = gcd(y-x,n);if(1 < d && d < n)return d;if(y == x)return n;if(i == k){y = x;k *= 2;}} } ll ans[1100],cnt; void getSmallest(ll n, int c) {if(n == 1)return;if(miller_rabbin(n)){ans[cnt++] = n;return;}ll val = n;while(val == n)val = PollarRho(n,c--);getSmallest(val,c);getSmallest(n/val,c); } ll a,b,sq; void choose(ll s,ll val) {if(s >= cnt){if(val > a && val <= sq)a = val;return;}choose(s+1,val);choose(s+1,val*ans[s]); }int main() {int T;ll G,L;while(~scanf("%lld%lld",&G,&L)){if(L == G){printf("%lld %lld\n",G,L);continue;}L /= G;cnt = 0;getSmallest(L,200);sort(ans, ans+cnt);int j = 0;for(int i = 1; i < cnt; i++){while(ans[i-1] == ans[i] && i < cnt)ans[j] *= ans[i++];if ( i < cnt )ans[++j] = ans[i];}cnt = j+1;a = 1;sq = (ll)sqrt(L+0.0);choose(0,1);printf("%lld %lld\n",a*G,L/a*G);}return 0; }JAVA
import java.util.Scanner;public class Main {static long gcd(long a,long b){long tmp;while (b!=0){tmp = b;b = a % b;a = tmp;}return a;}public static void main(String args[]){Scanner cin = new Scanner(System.in);long a,b,c,i;while (cin.hasNext()){a = cin.nextLong();b = cin.nextLong();c = b/a;for(i=(long)Math.sqrt(c); i>=1; i--){if(c%i==0&&gcd(i,c/i)==1){System.out.println((a*i)+" "+(b/i));break;}}}} }總結
以上是生活随笔為你收集整理的GCD and LCM Aizu - 0005(辗转相除)+GCD LCM Inverse POJ - 2429(java或【Miller Rabin素数測试】+【Pollar Rho整数分解】)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 糙米热量高为什么可以减肥
- 下一篇: Prime Number Aizu -