题目:
题解:
get到了新技能-------压位,以及一些逆天的结构体操作
首先gcd除了辗转相除法之外还有一个Stein(更相减损之术)算法,
如果a,b是偶数 gcd(a,b)=gcd(a/2,b/2)*2
如果a是偶数 b不是偶数 gcd(a,b)=gcd(a/2,b)
如果a不是偶数,b是偶数 gcd(a,b)=gcd(a,b/2)
如果a不是偶数,b也不是偶数 gcd(a,b)=gcd(abs(a-b),min(a,b))
这道题由于数据量大,所以可以把高精压一下位,压位可以适当提高速度
平常我们的高精中是一个int(char,unsigned char...)存1个数字
我们可以考虑一个int 里面存好多位,由于根据上面的算法,我们只需要乘2,除2,减法这三个运算,我们可以压9位(当然如果其他题的话,极有可能溢出,普通情况下,我们可以压3-4位提高速度)
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 1e9
using namespace std;
char sta[10005],stb[10005];
bool ff=true;
int la,lb,lc,s;
struct hh
{
int num[1050],l;
}a,b;
bool operator <(const hh &x,const hh &y)
{
if (x.l!=y.l) return x.l<y.l;
for (int i=x.l;i>=1;i--)
if (x.num[i]<y.num[i]) return true;
else if (x.num[i]>y.num[i]) return false;
return false;
}
void cl(int la,hh &a,char st[])
{
int i,j;
for (i=1;i<=a.l;i++)
{
for (j=max(la-8,1);j<=la;j++)
a.num[i]=a.num[i]*10+st[j]-'0';
la-=9;
}
}
void gchud(hh &a)
{
for (int i=a.l;i>=1;i--)
{
if (a.num[i]&1)//是奇数
a.num[i]--,a.num[i-1]+=inf;
a.num[i]>>=1;
}
if (!a.num[a.l])
a.l--;
}
void gchengd(hh &a)
{
for (int i=a.l;i>=1;i--)
{
a.num[i]<<=1;
if (a.num[i]>=inf) a.num[i]-=inf,a.num[i+1]++;
}
if (a.num[a.l+1]) a.l++;
}
void gjj(hh &a,hh &b)//a-b结果存a
{
int i;
for (i=1;i<=a.l;i++)
{
if (a.num[i]<b.num[i])
a.num[i]+=inf,a.num[i+1]--;
a.num[i]-=b.num[i];
}
while (!a.num[a.l] && a.l) a.l--;
}
void print(hh a)
{
printf("%d",a.num[a.l]);
for (int i=a.l-1;i>=1;i--)
printf("%09d",a.num[i]);
}
int main()
{
int i;
scanf("%s",sta+1);
scanf("%s",stb+1);
int la=strlen(sta+1),lb=strlen(stb+1);
if (la%9!=0) a.l++; a.l+=la/9;
if (lb%9!=0) b.l++; b.l+=lb/9;
cl(la,a,sta);
cl(lb,b,stb);
int hha=0;
while (1)
{
while (!(a.num[1]&1) && !(b.num[1]&1))
gchud(a),gchud(b),hha++;
while (!(a.num[1]&1)) gchud(a);
while (!(b.num[1]&1)) gchud(b);
if (a<b) gjj(b,a);
else gjj(a,b);
if (!a.l)
{
while (hha--) gchengd(b);
print(b);
break;
}
else if (!b.l)
{
while (hha--) gchengd(a);
print(a);
break;
}
}
}