【bzoj1876】[SDOI2009]SuperGCD(高精度)

  题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1876

  一道简单的高精度+Stein算法(或者叫辗转相除法)求最大公约数板子题。

  md还要压位。。

  代码:

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iostream> 
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define lowbit(x) (x& -x)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define eps 1e-18
#define maxn 100010
inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1; for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0'; return tmp*f;}
inline ll power(ll a,ll b){ll ans=1; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;}
using namespace std;
const int base=1000000000;
struct Bignum{
    int len;
    int num[1210];
    friend bool operator < (Bignum a,Bignum b){
        if(a.len!=b.len)return a.len<b.len;
        for(int i=a.len;i;i--)
            if(a.num[i]!=b.num[i])return a.num[i]<b.num[i];
        return 0; 
    }
    friend Bignum operator - (Bignum a,Bignum b){
        Bignum c;
        memset(&c,0,sizeof(c));
        for(int i=1;i<=a.len;i++){
            if(a.num[i]<b.num[i])a.num[i]+=base,--a.num[i+1];
            c.num[i]=a.num[i]-b.num[i];
        }
        c.len=a.len;
        while(c.len>1&&!c.num[c.len])--c.len;
        return c;
    }
    friend Bignum operator * (Bignum a,int b){
        Bignum c;
        memset(&c,0,sizeof(c)); ll tmp=0;
        for(int i=1;i<=a.len;i++){
            tmp+=a.num[i]*b;
            c.num[i]=tmp%base; tmp/=base;
        }
        c.len=a.len;
        for(;tmp;tmp/=base)c.num[++c.len]=tmp%base;
        return c;
    }
    friend Bignum operator / (Bignum a,int b){
        Bignum c;
        memset(&c,0,sizeof(c)); ll tmp=0;
        for(int i=a.len;i;i--){
            tmp=tmp*base+a.num[i];
            c.num[i]=tmp/b; tmp%=b;
        }
        c.len=a.len;
        while(c.len>1&&!c.num[c.len])--c.len;
        return c;
    }
    void print(Bignum a){
        printf("%d",a.num[a.len]);
        for(int i=a.len-1;i;i--)
            printf("%09d",a.num[i]);
        printf("\n"); 
    }
}a,b;
char A[10010],B[10010];
int n,m;
Bignum gcd(Bignum a,Bignum b)
{
    int cnt=0;
    while(1){
        if(a<b){
            Bignum tmp; tmp=a; a=b; b=tmp;
        }
        if(b.len==1&&b.num[1]==0)break;
        if(a.num[1]&1){
            if(b.num[1]&1){
                Bignum tmp; tmp=b; b=a-b; a=tmp;
            }
            else b=b/2;
        }
        else{
            if(b.num[1]&1)a=a/2;
            else ++cnt,a=a/2,b=b/2;
        }
    }
    Bignum ans=a;
    for(int i=20;i<=cnt;i+=20)ans=ans*(1<<20);
    for(int i=cnt%20;i;i--)ans=ans*2;
    return ans;
}
int main()
{
    scanf("%s",A); n=strlen(A);
    scanf("%s",B); m=strlen(B);
    a.len=b.len=0;
    for(int i=n-1;i>=0;i-=9){
        a.num[++a.len]=0;
        for(int j=max(i-8,0);j<=i;j++)
            a.num[a.len]=a.num[a.len]*10+A[j]-'0';
    }
    for(int i=m-1;i>=0;i-=9){
        b.num[++b.len]=0;
        for(int j=max(i-8,0);j<=i;j++)
            b.num[b.len]=b.num[b.len]*10+B[j]-'0';
    }
    Bignum ans=gcd(a,b);
    ans.print(ans);
}
bzoj1876

 

posted @ 2018-08-31 20:55  QuartZ_Z  阅读(191)  评论(0编辑  收藏  举报