bzoj1876[SDOI2009] SuperGCD
题目链接:bzoj1876
题目大意:
就是求GCD。对于100%的数据,0 < A , B ≤ 10 ^ 10000。
题解:
高精度+更相减损术
更相减损术就是设有两个数A,B
首先判断A,B是否都是偶数,如果都是的话就一直除2,直到有某个数不是偶数为止。gcd(A,B)中2这个因子的个数就等于除2的次数。—— ①
做完这一步的A,B就肯定不会再有2的因子了。
所以如果A,B中有某个数是偶数,就不要大意的把它砍半直到为奇数。—— ②
当两个都是奇数的时候就相减一下,重复这两个步骤(②③)。 —— ③
========================================
这样的一道题做了我好久QAQ(%%更相减损术
TLE完了WA一年!讲真,拍了巨久!嗨呀好气啊
不过,好像还挺快的~
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> using namespace std; #define maxn 11000 const int mod=100000000; struct node { int a[1500],len; node(){len=1;memset(a,0,sizeof(a));} }a,b; char s[maxn]; void read(node &c) { gets(s); int t,i,len,now=0; len=strlen(s);t=1; for (i=len-1;i>=0;i--) { now=now+(s[i]-'0')*t;t*=10; if ((len-i)%8==0) {c.a[c.len++]=now;now=0;t=1;} } if (now!=0) c.a[c.len++]=now;c.len--; } bool pz() { if (a.len!=b.len) return false; int i; for (i=a.len;i>=1;i--) if (a.a[i]!=b.a[i]) return false; return true; } bool comp() { if (a.len>b.len) return true; else if (a.len<b.len) return false; int i; for (i=a.len;i>=1;i--) if (a.a[i]>b.a[i]) return true; else if (a.a[i]<b.a[i]) return false; return true; } void ct(node &c,node d) { int i; for (i=1;i<=c.len;i++) { if (c.a[i]>=d.a[i]) c.a[i]-=d.a[i]; else {c.a[i]=c.a[i]+mod-d.a[i];c.a[i+1]-=1;} } while (c.a[c.len]==0 && c.len>1) c.len--; } void diva() { int i; for (i=a.len;i>=1;i--) { if (a.a[i]&1) a.a[i-1]+=mod; a.a[i]>>=1; } while (a.a[a.len]==0 && a.len>1) a.len--; } void divb() { int i; for (i=b.len;i>=1;i--) { if (b.a[i]&1) b.a[i-1]+=mod; b.a[i]>>=1; } while (b.a[b.len]==0 && b.len>1) b.len--; } void multi() { int i; for (i=a.len;i>=1;i--) { a.a[i]<<=1; if (a.a[i]>=mod) {a.a[i+1]++;a.a[i]-=mod;} } while (a.a[a.len+1]) a.len++; } void print() { int i; printf("%d",a.a[a.len]); for (i=a.len-1;i>=1;i--) printf("%08d",a.a[i]); printf("\n"); } int main() { int tot=0;read(a);read(b); while (!(a.a[1]&1) && !(b.a[1]&1)) {tot++;diva();divb();} while (!(a.a[1]&1)) diva(); while (!(b.a[1]&1)) divb(); while (!pz()) { if (comp()) ct(a,b); else ct(b,a); while (!(a.a[1]&1)) diva(); while (!(b.a[1]&1)) divb(); } while (tot--) multi(); print(); return 0; }