【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); }