bzoj1876: [SDOI2009]SuperGCD

来源:互联网 发布:彩票平台源码程序 编辑:程序博客网 时间:2024/06/05 12:57

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=1876

题解

  很显然是高精度gcd。。。

  从一开始我就是用的更相减损,好多人都坑我说:更相减损的复杂度大约是log的吧。我就没思考地信了。。。。但是所有点T了之后我才开始反思,有个很简单的例子就是,gcd(10^20,1)=gcd(10^20-1,1)=gcd(10^20-2,1)=gcd(10^20-3,1)...,这tm不是O(N)的么!

  考虑慢在哪里,如果a和b差的太多,那就要不断地减去b直到a<b。可以让b乘上10的某个次幂而使这个过程加速,而b乘上10的几次幂就是把这个数向左移多少位。移动的位数我就让它等于a的长度-b的长度-1。压位可过。

代码

//高精度 + 更相减损 #include <cstdio>#include <algorithm>#include <cstring>#define maxn 10010#define ll long longusing namespace std;long long a[maxn], b[maxn];char s[maxn];void input(){long long i;scanf("%s",s+1);a[0]=strlen(s+1);for(i=1;i<=a[0];i++)a[(a[0]-i)/9+1]=(a[(a[0]-i)/9+1]*10+s[i]-48);a[0]=(a[0]/9)+(a[0]%9!=0);scanf("%s",s+1);b[0]=strlen(s+1);for(i=1;i<=b[0];i++)b[(b[0]-i)/9+1]=(b[(b[0]-i)/9+1]*10+s[i]-48);b[0]=(b[0]/9)+(b[0]%9!=0);}inline bool cmp(long long *x, long long *y){if(x[0]<y[0])return true;if(x[0]>y[0])return false;for(long long i=x[0];i;i--)if(x[i]<y[i])return true;else if(x[i]>y[i])return false;return false;}void show(long long *x){long long i;printf("%lld",x[x[0]]);for(i=x[0]-1;i;i--){if(x[i]<100000000)printf("0");if(x[i]<10000000)printf("0");if(x[i]<1000000)printf("0");if(x[i]<100000)printf("0");if(x[i]<10000)printf("0");if(x[i]<1000)printf("0");if(x[i]<100)printf("0");if(x[i]<10)printf("0");printf("%lld",x[i]);}}void gcd(long long *x, long long *y){long long i, t, a;while(1){if(cmp(x,y))swap(x,y);if(y[0]==0){show(x);return;}t=max((ll)0,x[0]-y[0]-1);a=(x[y[0]+t]+x[y[0]+t+1]*1000000000)/(y[y[0]]+1);if(!a)a=1;for(i=1;i<=y[0];i++)x[i+t]-=a*y[i];for(i=1;i<x[0];i++)if(x[i]<0)x[i+1]+=x[i]/1000000000-(x[i]%1000000000!=0),x[i]=(x[i]%1000000000+1000000000)%1000000000;for(i=x[0];x[i]==0 and i;i--)x[0]--;}}int main(){input();gcd(a,b);return 0;}


0 0
原创粉丝点击