zoukankan      html  css  js  c++  java
  • 求两个超级大数的最大公约数

    由于给出的数太大了,所以我们将两个数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 }
  • 相关阅读:
    二叉排序树 常用函数小结
    二叉树的应用:二叉排序树的删除
    剑指 Offer 32
    剑指 Offer 32
    剑指 Offer 68
    剑指 Offer 28. 对称的二叉树 做题小结
    正则表达式不要背
    剑指 Offer 55
    LeetCode226. 翻转二叉树 做题小结
    Tools | 编程IED/编译器
  • 原文地址:https://www.cnblogs.com/ka200812/p/2665372.html
Copyright © 2011-2022 走看看