高精模板

#include <algorithm>
using std::min;
using std::max;
typedef unsigned long long ull;
typedef long long ll;
constexpr ull BASE = 100000000;
constexpr unsigned LEN = 10000/8 +5;
struct Big{
	ull num[LEN];
	int dig=0;
	void read(){
		char ch[LEN*8];
		int siz = 0;
		char c = getchar();
		while(c=='\n' || c=='\r') c=getchar();
		while(!(c=='\n' || c=='\r' || c==EOF)){
			ch[siz++] = c-'0';
			c = getchar();
		}
		--siz;
		int base = 1, now = 0;
		for(int i=0; i<=siz; ++i){
			now += ch[siz-i] * base;
			base *= 10;
			if(base == BASE){
				base = 1;
				num[dig++] = now;
				now = 0;
			}
		}
		num[dig++] = now;
	}
	void outp(){
		if(!dig) return;
		int i=dig-1;
		printf("%llu", num[dig-1]);
		if(i) do{
			--i;
			printf("%08llu", num[i]);
		} while(i);
	}
	void cary(){
		ull carry = 0;
		for(int i=0; i<dig; ++i){
			num[i] += carry;
			carry = num[i] / BASE;
			num[i] %= BASE;
		}
		while(carry){
			num[dig++] = carry%BASE;
			carry /= BASE;
		}
	}
	Big& operator+=(Big b){
		dig = max(dig, b.dig);
		for(int i=0; i<dig; ++i){
			num[i] += b.num[i];
		}
		this->cary();
		return *this;
	}
	bool operator<(Big b){
		if(dig == b.dig){
			for(int i=dig; i>=0; --i)
				if(num[i] != b.num[i]) return num[i] < b.num[i];
		}
		else return dig<b.dig;
		return false;
	}
	bool operator==(Big b){
		if(dig != b.dig) return false;
		for(int i=0; i<dig; ++i){
			if(num[i] != b.num[i]) return false;
		}
		return true;
	}
	Big& operator-=(Big b){
		// ensure a > b
		bool carry = 0;
		int newdig = 0;
		int maxlen = max(dig, b.dig);
		for(int i=0; i<maxlen; ++i){
			num[i] += (BASE - b.num[i] - carry);
			if(num[i] >= BASE){
				num[i] -= BASE;
				carry = 0;
			} else carry = 1;
			if(num[i]) newdig = i;
		}
		dig = newdig+1;
		return *this;
	}
	Big& half(){
		if(!dig) return *this;
		num[0] >>= 1;
		for(int i=1; i<dig; ++i){
			num[i-1] += ((num[i]&1)*BASE)>>1;
			num[i] >>= 1;
		}
		if(!num[dig-1]) dig--;
		return *this;
	}
	Big& operator<<=(unsigned times){
		// << 37 : inside ull
		constexpr int MOST = 37;
		while(times>MOST){
			*this <<= MOST;
			times -= MOST;
		}
		for(int i=0; i<dig; ++i){
			num[i] <<= times;
		}
		this->cary();
		return *this;
	}
	bool iseven(){
		return !(num[0]&1);
	}
};
Big gcd(Big a, Big b){
	int at=0, bt=0;
	while(a.iseven()) a.half(), ++at;
	while(b.iseven()) b.half(), ++bt;
	for(;;){
		while(a.iseven()) a.half();
		while(b.iseven()) b.half();
		if(a==b) break;
		if(a<b) std::swap(a, b);
		a-=b;
	}
	return a <<= min(at, bt);
}
posted @ 2023-01-20 12:56  383494  阅读(11)  评论(0编辑  收藏  举报