[SDOI2009] SuperGCD
题目描述
Sheng bill 有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的最大公约数!因此他经常和别人比赛计算最大公约数。有一天Sheng bill很嚣张地找到了你,并要求和你比赛,但是输给 Sheng bill 岂不是很丢脸!所以你决定写一个程序来教训他。
输入格式
共两行,第一行一个整数 a a a,第二行一个整数 b b b。
输出格式
一行,表示 a a a 和 b b b 的最大公约数。
样例 #1
样例输入 #1
12
54
样例输出 #1
6
提示
数据规模与约定
- 对于 20 % 20\% 20% 的数据,有 0 < a , b ≤ 1 0 18 0<a,b\le 10^{18} 0<a,b≤1018。
- 对于 100 % 100\% 100% 的数据,有 0 < a , b ≤ 1 0 10000 0<a,b\le 10^{10000} 0<a,b≤1010000。
前置芝士
**
更相减损术
若a偶&&b偶 将a/=2,b/=2;
若a偶&&b奇 a/=2;
若a奇&&b偶 b/=2
**
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
char s[N];
struct node{
int len,num[N];
friend node operator /(const node&a,const int &b)
{
node tmp=a;
int num=0;
for(int i=tmp.len;i;i--)
{
num=num*10+a.num[i];
tmp.num[i]=num/b;
num%=b;
}
while(tmp.num[tmp.len]==0&&tmp.len>1) tmp.len--;
return tmp;
}
int cmp(const node&b)const
{
if(len<b.len) return -1;
if(len>b.len) return 1;
for(int i=len;i;i--)
{
if(b.num[i]>num[i]) return -1;
if(b.num[i]<num[i]) return 1;
}
return 0;
}
friend node operator -(node&a,const node&b)
{
node tmp;tmp.len=a.len;
for(int i=1;i<=tmp.len;i++)
{
if(a.num[i]<b.num[i]) a.num[i]+=10,a.num[i+1]--;
tmp.num[i]=a.num[i]-b.num[i];
}
while(tmp.num[tmp.len]==0&&tmp.len>1) tmp.len--;
return tmp;
}
friend node operator *(node&a,const int&b)
{
node tmp;int num=0;
tmp.len=a.len;
memset(tmp.num,0,sizeof tmp.num );
for(int i=1;i<=tmp.len;i++)
{
tmp.num[i]+=a.num[i]*b;
if(tmp.num[i]>=10)
{
tmp.num[i+1]+=tmp.num[i]/10;
tmp.num[i]%=10;
if(tmp.len==i)
tmp.len++;
}
}
return tmp;
}
}a,b;
int main()
{
scanf("%s",s+1);
a.len=strlen(s+1);
for(int i=1;i<=a.len;i++)
a.num[a.len-i+1]=s[i]-48;
scanf("%s",s+1);
b.len=strlen(s+1);
for(int i=1;i<=b.len;i++)
b.num[b.len-i+1]=s[i]-48;
int even=0;
while(!(a.num[1]&1)&&!(b.num[1]&1)) even++,a=a/2,b=b/2;
while(!(a.num[1]&1)) a=a/2;
while(!(b.num[1]&1)) b=b/2;
while(a.cmp(b)!=0)
{
if(a.cmp(b)==1)
a=a-b;
else b=b-a;
while(!(a.num[1]&1)) a=a/2;
while(!(b.num[1]&1)) b=b/2;
}
while(even--)
a=a*2;
for(int i=a.len;i>=1;i--)
cout<<a.num[i];
return 0;
}