数论superGCD 高精度GCD

高精度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);
数论持续更新

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值