大位数的最大公约数 (高精度最大公约数)
以洛谷 P2152 [SDOI2009]SuperGCD为例
1、python解法
对于大位数的处理当然是能用python就用python
python有专门的math库,直接调用求gcd的函数
import math;print(math.gcd(int(input()), int(input())))
2、C++解法
c++的大位数用辗转相除法不太好写。
本处用辗转相减法比较容易。
对于 a,b 的 GCD(a, b)有:
[1]. 若 a 为奇数,b 为偶数,GCD(a, b) = GCD(a, b / 2)
表示 b 存在2这个因子而 a 不存在,则将 b 除以2,,不考虑因子2;
[2]. 若 a 为偶数,b 为奇数,GCD(a, b) = GCD(a / 2, b)
表示 a 存在2这个因子而 b 不存在,则将 a 除以2,不考虑因子2;
[3]. 若 a 为偶数,b 为偶数,GCD(a, b) = GCD(a / 2, b / 2)
表示 a, b 都存在2这个因子,则 GCD(a, b) 也存在因子2,则将当前答案乘以2,a,b 都除以2;
[4]. 若 a 为奇数,b 为奇数,GCD(a, b) = GCD(a - b, b) (a > b)
3、例题
3.1链接
3.2题意
求两个大位数的最大公约数
3.3代码
本题对时间和空间要求较高,要压16位,要提高代码能力的好题。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <time.h>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
const int maxn = 630;
const LL base = 1e16, width = 16;
char s[maxn << 4];
int cnt;
struct BigInteger
{
LL data[maxn], size;
void init(){
memset(data, 0, sizeof(data));
size = 0;
}
void Print()
{
if (size == 0)
putchar('0');
else
{
printf("%lld", data[size]);
for (int i = size - 1; i >= 1; i--)
printf("%016lld", data[i]);
}
putchar('\n');
}
BigInteger operator =(LL num) {
init();
while (num > 0) {
s[++size] = num % base;
num /= base;
}
return *this;
}
BigInteger operator =(const char *s){
init();
LL numlen = strlen(s); size = (numlen + width - 1) / width;
int lastsize = numlen % width; LL value = 0;
if (lastsize == 0)lastsize = 16;
if (size) {
for (int i = 0; i < lastsize; i++)
value = value * 10 + s[i] - '0';
data[size] = value;
}
for (int t = size - 1, i = lastsize; t > 0; t--) {
value = 0;
for (int j = 0; j < 16; j++, i++)
value = value * 10 + s[i] - '0';
data[t] = value;
}
return *this;
}
bool operator <(const BigInteger &t)const{
if (t.size != size)
return size < t.size;
for (int i = size; i >= 1; i--)
if (data[i] != t.data[i])
return data[i] < t.data[i];
return false;
}
bool operator ==(const BigInteger &t)const{
return (!(*this < t)) && (!(t < *this));
}
BigInteger operator -(const BigInteger &t)const{
BigInteger res;
res.init();
res.size = size;
for (int i = 1; i <= size; i++)
{
res.data[i] += data[i] - t.data[i];
if (res.data[i] < 0)
{
res.data[i] += base;
res.data[i + 1]--;
}
}
while (res.data[res.size] == 0 && res.size > 0)
res.size--;
return res;
}
void mul()
{
for (int i = 1; i <= size; i++)
data[i] <<= 1;
size += 5;
for (int i = 1; i <= size; i++)
{
data[i + 1] += data[i] / base;
data[i] %= base;
}
while (data[size] == 0 && size > 0)
size--;
}
void div()
{
for (int i = size; i >= 1; i--)
{
if (data[i] & 1)
data[i - 1] += base;
data[i] >>= 1;
}
while (data[size] == 0 && size > 0)
size--;
}
};
BigInteger a, b, ans;
BigInteger Gcd(BigInteger &a, BigInteger &b)
{
while (!(a == b))
{
if (a < b)
swap(a, b);
if (b.size == 0)
break;
if (!(a.data[1] & 1) && !(b.data[1] & 1))
a.div(), b.div(), cnt++;
else if (!(a.data[1] & 1))
a.div();
else if (!(b.data[1] & 1))
b.div();
else
a = a - b;
}
return a;
}
int main()
{
a.init(); b.init(); ans.init();
scanf("%s", s);
a = s;
scanf("%s", s);
b = s;
ans = Gcd(a, b);
while (cnt--)
ans.mul();
ans.Print();
}