链接
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 long
using 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;
}