[SDOI2009]SuperGCD

Posted wolfycz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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('
');
    }
}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();
}

以上是关于[SDOI2009]SuperGCD的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1876: [SDOI2009]SuperGCD

bzoj1876 [SDOI2009]SuperGCD

P2152 [SDOI2009]SuperGCD(模拟)

BZOJ1876: [SDOI2009]SuperGCD

P2152 [SDOI2009]SuperGCD

[SDOI2009]SuperGCD