【洛谷P2152】SuperGCD【高精度】
题目大意:
题目链接:https://www.luogu.org/problemnew/show/P2152
求两个整数的最大公约数。
思路:
神题啊。
# py3
import fractions
print(fractions.gcd(int(input()),int(input())))
本题要用到更相减损法。没有了解过的请自行度娘
然后利用更相减损法就可以愉快的过掉飞。
例如:
你需要才能搞定。
那么应该怎么样呢?
可以考虑数的奇偶性。
设两个数为和,那么
- 若和都是偶数,那么他们就都有公因子,于是和分别除以,。
- 若是偶数,是奇数,那么他们肯定没有公因子,直接除以就可以了。
- 若是偶数,是奇数,同。
- 若都是奇数,那么直接更相减损即可。
那么很明显时间复杂度最不优秀的是,但是奇数奇数会出现偶数,所以又可以除以了。
所以最坏的时间复杂度是。
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int MAXN=1500;
const ll maxint=1e8;
int len,sum;
ll a[MAXN+1],b[MAXN+1];
char ch[10010];
bool check()
{
for (int i=1;i<=MAXN;i++)
if (b[i]) return 0;
return 1;
}
void div2(ll a[]) //除以2
{
for (int i=1;i<=MAXN;i++)
{
if (a[i]&1) a[i+1]+=maxint;
a[i]/=2;
}
}
void mul2(ll a[]) //乘2
{
ll t=0;
for (int i=MAXN;i>=1;i--)
{
a[i]=a[i]*2+t;
t=a[i]/maxint;
a[i]%=maxint;
}
}
bool check_swap()
{
for (int i=1;i<=MAXN;i++)
if (a[i]>b[i]) return 0;
else if (b[i]>a[i]) return 1;
return 0;
}
void sub(ll a[]) //减法
{
for (int i=MAXN;i>=1;i--)
{
if (b[i]>a[i])
{
a[i-1]--;
a[i]+=maxint;
}
a[i]-=b[i];
}
}
int main()
{
cin>>ch;
len=strlen(ch);
for (int i=1;i<=len;i++)
a[MAXN-(len-i)/8]=a[MAXN-(len-i)/8]*10+ch[i-1]-48;
cin>>ch;
len=strlen(ch);
for (int i=1;i<=len;i++)
b[MAXN-(len-i)/8]=b[MAXN-(len-i)/8]*10+ch[i-1]-48;
if (check_swap()) swap(a,b);
while (!check())
{
if (!(a[MAXN]&1)&&!(b[MAXN]&1))
div2(a),div2(b),sum++;
else if (!(a[MAXN]&1))
div2(a);
else if (!(b[MAXN]&1))
div2(b);
else sub(a);
if (check_swap()) swap(a,b);
}
for (int i=1;i<=sum;i++)
mul2(a);
int i=1;
while (!a[i]) i++;
printf("%lld",a[i]);
for (i++;i<=MAXN;i++)
{
if (a[i]<10) putchar(48);
if (a[i]<100) putchar(48);
if (a[i]<1000) putchar(48);
if (a[i]<10000) putchar(48);
if (a[i]<100000) putchar(48);
if (a[i]<1000000) putchar(48);
if (a[i]<10000000) putchar(48);
printf("%lld",a[i]);
}
return 0;
}