求两个超级大数的最大公约数

由于给出的数太大了,所以我们将两个数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>容器。

 

View Code
 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 }

 

 

你可能感兴趣的:(求两个超级大数的最大公约数)