数论superGCD 高精度GCD

匿名 (未验证) 提交于 2019-12-02 23:26:52

高精度GCD
https://www.luogu.org/problemnew/show/P2152是一道模板题,因为不会phython,所以・・・只能老老实实写高精度。这里我们用到更相减损法求公约数。


首先,根据上面的步骤,分析他们是否是偶数,所以需要检查每个大数的最后一位;直到两个都是奇数,然后用大数减去小数,减去之后再重复之前的操作,然后把最后的数乘上若干个2就可以了;
分析操作过程,我们需要处理高精度判断奇偶数高精度乘2高精度除2高精度减法这四个操作。
自己也是看了网上很多代码,然后照猫画虎,能改进的地方有很多。

高精度判断奇偶数

 bool judge(const node &a)  {   return a.num[0]%2==0?//判断最后一位就好  } 

高精度乘2

node mul2(node a) {   int in=0;  for(int i=0;i<a.len;i++)  {   a.num[i]=a.num[i]*2+in;   in=0;   if(a.num[i]>=10)   {    in=a.num[i]/10;    a.num[i]%=10;    if(i==a.len-1)    a.len++;    }  }  return a; } 

高精度除2

node div2(node a) {  for(int i=a.len-1;i>=1;i--)//这里是1,0的话会出现a.num[-1]的情况     {      a.num[i-1]+=a.num[i]%2*10;//这一步可以自己去运算试试就明白了,运算的时候数是反过来的//反了两次就变正序了      a.num[i]/=2;  }  a.num[0]/=2;  while(a.num[a.len-1]==0)a.len--;//去除前导0  return a; } 

高精度减法

struct node {  ll num[maxn],len;  void clear()//清空一个node类型  {   memset(num,0,sizeof(num));   len=0;   return ;  }  node operator - (const node &a)重载 - 号,变成高精度减法  {   big a1;   a1.clear();   a1.len=max(a1.len,len);   fin(0,a1.len-1)   {    a1.num[i]+=(num[i]-a.num[i]);//从个位减,不够则从上面一位取    if(a1.num[i]<0)    {     a1.num[i]+=10;     a1.num[i+1]--;    }   }   return a1;  }  node operator <(const node &a)//重载<号,因为一会儿要比较大小  {   if(a.len!=len)return len<a.len;   for(int i=len-1;i>=0;i--)   {    if(a.num[i]!=num[i])return num[i]<a.num[i];   }   return false;  }  node operator ==(const node &a)//判断两个是否相等,相等则得到结果  {   if(a.len!=len)return false;   fin(0,a.len-1)if(a.num[i]!=num[i])return false;   return true;  } }; 

完整代码

#include<bits/stdc++.h> using namespace std; #define fin(a,n) for(int i=a;i<=n;i++) #define ll long long int const int maxn=1e4+27; struct node {  int num[maxn],len;  void clear()  {   memset(num,0,sizeof(num));   len=0;   return ;  }  node operator - (const node &a)  {   node a1;   a1.clear();   a1.len=max(a1.len,len);   fin(0,a1.len-1)   {    a1.num[i]+=(num[i]-a.num[i]);    if(a1.num[i]<0)    {     a1.num[i]+=10;     a1.num[i+1]--;    }   }   return a1;  }  bool operator <(const node &a)  {   if(a.len!=len)return len<a.len;   for(int i=len-1;i>=0;i--)   {    if(a.num[i]!=num[i])return num[i]<a.num[i];   }   return false;  }  bool operator ==(const node &a)  {   if(a.len!=len)return false;   fin(0,a.len-1)if(a.num[i]!=num[i])return false;   return true;  } };  bool judge(const node &a)  {   return a.num[0]%2==0;  } node mul2(node a) {   int in=0;  for(int i=0;i<a.len;i++)  {   a.num[i]=a.num[i]*2+in;   in=0;   if(a.num[i]>=10)   {    in=a.num[i]/10;    a.num[i]%=10;    if(i==a.len-1)    a.len++;    }  }  return a; } node div2(node a) {  for(int i=a.len-1;i>=1;i--)     {      a.num[i-1]+=a.num[i]%2*10;      a.num[i]/=2;  }  a.num[0]/=2;  while(a.num[a.len-1]==0)a.len--;  return a; } int main() {  char s[maxn];  char ss[maxn];  scanf("%s %s",s,ss);  int cnt2=0;  node s1,s2;  bool js1,js2;  s1.len=strlen(s);  fin(0,s1.len-1)s1.num[i]=s[s1.len-1-i]-'0';  s2.len=strlen(ss);  fin(0,s2.len-1)s2.num[i]=ss[s2.len-1-i]-'0';  while(!(s1==s2))//下面就是更相减损法  {   if(s1<s2)swap(s1,s2);   js1=judge(s1);   js2=judge(s2);   if(js1&&js2)   {    s1=div2(s1);    s2=div2(s2);    cnt2++;//两个都为偶数,2的指数就+1    }   else if(js1)s1=div2(s1);//一个为偶数,指数不加,直接除   else if(js2)s2=div2(s2);   else s1=s1-s2;//都为奇数,大减小。  }  fin(1,cnt2)s1=mul2(s1);  for(int i=s1.len-1;i>=0;i--)printf("%d",s1.num[i]);  return 0;   } 

实际上当a,b,为偶数时gcd(a,b)==2*gcd(a/2,b/2);
数论持续更新

文章来源: https://blog.csdn.net/weixin_44203780/article/details/88852389
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!