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