1. 程式人生 > >【題解】洛谷P2152[SDOI2009]Super GCD 高精度+更相減損術

【題解】洛谷P2152[SDOI2009]Super GCD 高精度+更相減損術

題目連結

題目描述

Sheng bill有著驚人的心算能力,甚至能用大腦計算出兩個巨大的數的GCD(最大公約 數)!因此他經常和別人比賽計算GCD。有一天Sheng bill很囂張地找到了你,並要求和你比 賽,但是輸給Sheng bill豈不是很丟臉!所以你決定寫一個程式來教訓他。

輸入輸出格式

輸入格式:

共兩行: 第一行:一個數AA。 第二行:一個數BB

輸出格式:

一行,表示AABB的最大公約數。

輸入輸出樣例

輸入樣例#1:

12 54

輸出樣例#1:

6

說明

對於20%20\%的資料,0<A,B10180 < A , B\le10 ^{18}

A,B1018。 對於100%100\%的資料,0<A,B10100000 < A , B \le 10 ^{10000}

1.a<bgcd(a,b)=gcd(b,a)1.a<b時,\gcd(a,b)=\gcd(b,a) 2.a=bgcd(a,b)=a2.a=b時,\gcd(a,b)=a 3.a,bgcd(a,b)=2×gcd(a÷2,b÷2)3.a,b同為偶數時,\gcd(a,b)=2\times \gcd(a\div 2,b\div 2)

4.abgcd(a,b)=gcd(a÷2,b)4.a為偶數,b為奇數時,\gcd(a,b)=\gcd(a\div 2,b) 5.abgcd(a,b)=gcd(a,b÷2)5.a為奇數,b為偶數時,\gcd(a,b)=\gcd(a,b\div 2) 6.abgcd(a,b)=gcd(ab,b)6.a,b同為奇數時,\gcd(a,b)=\gcd(a-b,b)

#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
const int N=1e4+10;
char s[N];
struct BigNum{
	int len,num[N];
	friend BigNum operator /(const BigNum&a,const int&b)
	{
		BigNum 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 BigNum&b)const
	{
		if(len<b.len)return -1;
		if(len>b.len)return 1;
		for(int i=len;i;i--)
		{
			if(num[i]<b.num[i])return -1;
			if(num[i]>b.num[i])return 1;
		}
		return 0;
	}
	friend BigNum operator -(BigNum&a,const BigNum&b)
	{
		BigNum 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 BigNum operator *(const BigNum&a,const int&b)
	{
		BigNum tmp;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]>9)
			{
				tmp.num[i+1]+=tmp.num[i]/10;tmp.num[i]%=10;if(tmp.len==i)tmp.len++;
			}
		}
		return tmp;
	}
}a,b;
int main()
{
	//freopen("in.txt","r",stdin);
    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]-'0';
    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]-'0';
    int dou=0;
    while(!(a.num[1]&1)&&!(b.num[1]&1))dou++,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(dou--)a=a*2;
	for(int i=a.len;i;i--)printf("%d",a.num[i]);
	return 0;
}

總結

高精度的最大公約數