大位数的最大公约数 (高精度最大公约数)以洛谷 P2152 [SDOI2009]SuperGCD为例

大位数的最大公约数 (高精度最大公约数)

                                                以洛谷 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();
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值