由于给出的数太大了,所以我们将两个数A,B拆成了N个数相乘和M个数相乘的形式。N,M<=1000,拆成的数<=1000000000。是不是够大?
最终的结果最多保留9位输出。
例如:
3
358572 83391967 82
3
50229961 1091444 8863
输出为:
000012028
根据欧拉公式,我们可以将任何一个数表示成如下形式:
n=p1^x1*p2^x2*p3^x3.......*pm^xm;
如果将A和B分别表示成
A = p1^a1 * p2^a2 * … * pn^an
B = p1^b1 * p2^b2 * … * pn^bn
其中p1,p2....都是素数,a1,a2...都是整数
那么
GCD( A, B ) = p1^min(a1,b1) * p2^min(a2,b2) * … * pn^min(an,bn)。
对于任何一个整数,我们可以快速的将它因式分解
scanf("%d",&a); for(j=2;j*j<=a;j++) { while(a%j==0) a/=j,A[j]++; } if(a>1) A[a]++;
对于这样由N个数乘积组成的数,我们可以将N个数的拆分结果全部保存在同一个A数组中,最终的结果就是超大数自身的拆分。
还有一个需要注意的是,给出的a<=1000000000,直接开数组内存上和时间上都很吃力,所以推荐用map<int,int>容器。
1 #include<iostream> 2 #include<string> 3 #include<map> 4 using namespace std; 5 #define mod 1000000000 6 7 map<int,int>A,B; 8 int n,m,a; 9 __int64 ans; 10 11 int min(int a,int b) 12 { 13 return a<b?a:b; 14 } 15 16 int main() 17 { 18 int i,j; 19 freopen("D:\\in.txt","r",stdin); 20 while(scanf("%d",&n)==1) 21 { 22 A.clear();B.clear(); 23 for(i=0;i<n;i++) 24 { 25 scanf("%d",&a); 26 for(j=2;j*j<=a;j++) 27 { 28 while(a%j==0) 29 a/=j,A[j]++; 30 } 31 if(a>1) 32 A[a]++; 33 } 34 scanf("%d",&m); 35 for(i=0;i<m;i++) 36 { 37 scanf("%d",&a); 38 for(j=2;j*j<=a;j++) 39 { 40 while(a%j==0) 41 a/=j,B[j]++; 42 } 43 if(a>1) 44 B[a]++; 45 } 46 ans=1; 47 int flag=0; 48 map<int,int>::iterator it; 49 for(it=A.begin();it!=A.end();it++) 50 { 51 if(B.count(it->first)) 52 { 53 int p=it->first; 54 int r=min(A[p],B[p]); 55 for(i=0;i<r;i++) 56 { 57 ans*=p; 58 if(ans>=mod) 59 { 60 ans%=mod; 61 flag=1; 62 } 63 } 64 } 65 } 66 if(flag) 67 printf("%09d\n",(int)ans); 68 else 69 printf("%I64d\n",ans); 70 } 71 return 0; 72 }