[SDOI2009]SuperGCD

Description
Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你决定写一个程序来教训他。

Input
共两行: 第一行:一个数A。 第二行:一个数B。
0 < A , B ≤ 10 ^ 10000。

Output
一行,表示A和B的最大公约数。

Sample Input
12
54

Sample Output
6


写个高精度取模,这题就没了。。。

其实没比要写高精度取模,其实辗转相除法的前身是更相减损术,具体可以去百度或Google

流程如下:

  1. 给定两个数A,B,令A>B
  2. 若A,B都能被2整除,则让A和B都除2,将答案乘2,并重复执行步骤2
  3. 若A能被2整除,则让A除2,直至不能被2整除
  4. 若B能被2整除,则让B除2,直至不能被2整除
  5. 若A,B相等,则将答案乘上A,并且退出,否则执行步骤6
  6. 令A=A-B,若此时A<B,则交换A,B,并且执行步骤2

初始时将答案设为1

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
	int x=0,f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline int read(){
	int x=0,f=1; char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)	putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int digit=8;
const int base=1e8;
const int maxn=1.3e3;
char s[maxn*digit];
struct Bignum{
	int v[maxn],len;
	Bignum(){memset(v,0,sizeof(v)),len=1;}
	void init(){v[0]=1;}
	void read(){
		char ch=gc(); int t=0,tim=1;
		for (;ch<'0'||ch>'9';ch=gc());
		for (;ch>='0'&&ch<='9';ch=gc()) s[t++]=ch;
		len=(t-1)/digit+1;
		for (int i=0,j=t-1;i<j;i++,j--)	swap(s[i],s[j]);
		for (int i=0;i<t;i++){
			v[i/digit]+=tim*(s[i]-'0'),tim*=10;
			if (tim==base)	tim=1;
		}
	}
	void write(){
		printf("%d",v[len-1]);
		for (int i=len-2;~i;i--)	printf("%0*d",digit,v[i]);
		putchar('\n');
	}
}A,B;
Bignum operator -(const Bignum &x,const Bignum &y){
	Bignum z;
	z.len=max(x.len,y.len);
	for (int i=0;i<=z.len;i++){
		z.v[i]+=x.v[i]-y.v[i];
		if (z.v[i]<0)	z.v[i]+=base,z.v[i+1]--;
	}
	while (!z.v[z.len]&&z.len>1)	z.len--;
	while (z.v[z.len])	z.v[z.len+1]+=z.v[z.len]/base,z.v[z.len]%=base,z.len++;
	return z;
}
Bignum operator *(const Bignum &x,int y){
	Bignum z;
	z.len=x.len;
	for (int i=0;i<=x.len;i++)	z.v[i]+=x.v[i]*y,z.v[i+1]+=z.v[i]/base,z.v[i]%=base;
	while (z.v[z.len])	z.v[z.len+1]+=z.v[z.len]/base,z.v[z.len]%=base,z.len++;
	return z;
}
Bignum operator /(const Bignum &x,int y){
	Bignum z; z=x;
	for (int i=z.len;i;i--)	z.v[i-1]+=z.v[i]%y*base,z.v[i]/=y; z.v[0]/=y;
	while (!z.v[z.len]&&z.len>1)	z.len--;
	while (z.v[z.len])	z.v[z.len+1]+=z.v[z.len]/base,z.v[z.len]%=base,z.len++;
	return z;
}
bool operator <(const Bignum &x,const Bignum &y){
	if (x.len!=y.len)	return x.len<y.len;
	for (int i=x.len;~i;i--)	if (x.v[i]!=y.v[i])	return x.v[i]<y.v[i];
	return 1;
}
bool operator ==(const Bignum &x,const Bignum &y){
	if (x.len!=y.len)	return 0;
	for (int i=0;i<=x.len;i++)	if (x.v[i]!=y.v[i])	return 0;
	return 1;
}
int main(){
	A.read(),B.read();
	if (A<B)	swap(A,B);
	int num=0;
	while (true){
		int cntA=0,cntB=0;
		while (A.v[0]%2==0)	A=A/2,cntA++;
		while (B.v[0]%2==0)	B=B/2,cntB++;
		num+=min(cntA,cntB);
		if (A==B)	break;
		if (A<B)	swap(A,B);
		A=A-B;
	}
	for (int i=1;i<=num;i++)	A=A*2;
	A.write();
}
posted @ 2018-11-21 11:21  Wolfycz  阅读(193)  评论(0编辑  收藏  举报