Gaotianjia @ 2022-12-26 03:24:33
// 长整数的奇怪实现.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<string>
using namespace std;
string s;
string z;
int n;
bool show0 = false;
void out(long long& a) {
string s = to_string(a);
int k = s.length();
string p = "";
for (int j = 0; j < 16 - k; j++) {
p += "0";
}
s = p + s;
cout << s;
}
class num_1 {
public:
static long long H;
static long long E;
long long high;
long long low;
long long exceed;
num_1() {
high = low = 0;
exceed = 0;
}
void out() {
::out(high);
::out(low);
}
void out1() {
if (!show0)
{
if (high == 0) {
cout << low;
}
else {
cout << high;
show0 = true;
::out(low);
}
}
else
{
out();
}
}
num_1 operator+(num_1& b) {
num_1 ans = *this;
ans = ans + b.low;
ans.high += b.high;
return ans;
}
num_1 operator+(long long& b) {
num_1 ans = *this;
ans.low += b;
if (ans.low > H) {
ans.low -=(H + 1);
ans.high += 1;
}
return ans;
}
bool operator==(num_1& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_1& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_1& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high -= (H + 1);
}
static num_1 mul(long long& a, long long& b) {
long long p1 = a % 100000000;
long long p2 = a / 100000000;
long long p3 = b % 100000000;
long long p4 = b / 100000000;
long long q1 = p1 * p3;
long long q2 = p2 * p3;
long long q3 = p4 * p1;
long long q4 = p4 * p2;
num_1 ans;
ans.low = q1 + (q2 % 100000000) * 100000000 + (q3 % 100000000) * 100000000;
ans.high = q4 + q2 / 100000000 + q3 / 100000000;
if (ans.low > 9999999999999999) {
ans.high += ans.low / 10000000000000000;
ans.low %= 10000000000000000;
}
return ans;
}
void in(string& s,int a) {
low = high = 0;
long long temp = 1;
int i = a;
for (; i < (a + 16); i++) {
if (i >= ::n) {
return;
}
else
{
low = low + temp * (s[i] - '0');
temp *= 10;
}
}
temp = 1;
for (; i < (a + 32); i++) {
if (i >= ::n) {
break;
}
else
{
high = high + temp * (s[i] - '0');
temp *= 10;
}
}
}
};
long long num_1::H;
long long num_1::E;
class num_2 {
public:
num_1 high;
num_1 low;
static num_1 H;
static num_1 E;
num_2() {
high = low = num_1();
}
void out() {
high.out();
low.out();
}
void out1() {
num_1 t;
if (!show0)
{
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
else
{
out();
}
}
num_2 static mul(num_1& m, num_1& n) {
num_1 q1 = num_1::mul(m.low, n.low);
num_1 q2 = num_1::mul(m.high, n.low);
num_1 q3 = num_1::mul(n.high, m.low);
num_1 q4 = num_1::mul(m.high, n.high);
num_2 ans;
ans.low = q1;
num_1 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_1::H) {
ans.high.low -= (num_1::H + 1);
ans.high.high += 1;
}
ans.high = ans.high + q4;
return ans;
}
num_2 operator+(num_1& b) {
num_2 ans = *this;
ans.low = ans.low + b;
if (ans.low > H ) {
ans.low.clearhigh();
long long t = 1;
ans.high = ans.high + t;
}
return ans;
}
num_2 operator+(num_2& b) {
num_2 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_2& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_2& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_2& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s,int a) {
high.in(s, a + 32);
low.in(s, a);
}
};
num_1 num_2::H;
num_1 num_2::E;
class num_3 {
public:
num_2 high;
num_2 low;
static num_2 H;
static num_2 E;
num_3() {
high = low = num_2();
}
void out() {
high.out();
low.out();
}
void out1() {
num_2 t;
if (!show0)
{
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
else
{
out();
}
}
num_3 static mul(num_2& m, num_2& n) {
num_2 q1 = num_2::mul(m.low, n.low);
num_2 q2 = num_2::mul(m.high, n.low);
num_2 q3 = num_2::mul(n.high, m.low);
num_2 q4 = num_2::mul(m.high, n.high);
num_3 ans;
ans.low = q1;
num_2 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_2::H) {
ans.high.low.clearhigh();
ans.high.high = ans.high.high + num_2::E;
}
ans.high = ans.high + q4;
return ans;
}
num_3 operator+(num_2& b) {
num_3 ans = *this;
ans.low = ans.low + b;
if (ans.low > H) {
ans.low.clearhigh();
ans.high = ans.high + num_2::E;
}
return ans;
}
num_3 operator+(num_3& b) {
num_3 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_3& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_3& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_3& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s, int a) {
high.in(s, a + 64);
low.in(s, a);
}
};
num_2 num_3::H;
num_2 num_3::E;
class num_4 {
public:
num_3 high;
num_3 low;
static num_3 H;
static num_3 E;
num_4() {
high = low = num_3();
}
void out() {
high.out();
low.out();
}
void out1() {
num_3 t;
if (!show0)
{
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
else
{
out();
}
}
num_4 static mul(num_3& m, num_3& n) {
num_3 q1 = num_3::mul(m.low, n.low);
num_3 q2 = num_3::mul(m.high, n.low);
num_3 q3 = num_3::mul(n.high, m.low);
num_3 q4 = num_3::mul(m.high, n.high);
num_4 ans;
ans.low = q1;
num_3 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_3::H) {
ans.high.low.clearhigh();
ans.high.high = ans.high.high + num_3::E;
}
ans.high = ans.high + q4;
return ans;
}
num_4 operator+(num_3& b) {
num_4 ans = *this;
ans.low = ans.low + b;
if (ans.low > H) {
ans.low.clearhigh();
ans.high = ans.high + num_3::E;
}
return ans;
}
num_4 operator+(num_4& b) {
num_4 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_4& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_4& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_4& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s, int a) {
high.in(s, a + 128);
low.in(s, a);
}
};
num_3 num_4::H;
num_3 num_4::E;
class num_5 {
public:
num_4 high;
num_4 low;
static num_4 H;
static num_4 E;
num_5() {
high = low = num_4();
}
void out() {
high.out();
low.out();
}
void out1() {
num_4 t;
if (!show0)
{
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
else
{
out();
}
}
num_5 static mul(num_4& m, num_4& n) {
num_4 q1 = num_4::mul(m.low, n.low);
num_4 q2 = num_4::mul(m.high, n.low);
num_4 q3 = num_4::mul(n.high, m.low);
num_4 q4 = num_4::mul(m.high, n.high);
num_5 ans;
ans.low = q1;
num_4 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_4::H) {
ans.high.low.clearhigh();
ans.high.high = ans.high.high + num_4::E;
}
ans.high = ans.high + q4;
return ans;
}
num_5 operator+(num_4& b) {
num_5 ans = *this;
ans.low = ans.low + b;
if (ans.low > H) {
ans.low.clearhigh();
ans.high = ans.high + num_4::E;
}
return ans;
}
num_5 operator+(num_5& b) {
num_5 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_5& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_5& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_5& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s, int a) {
high.in(s, a + 256);
low.in(s, a);
}
};
num_4 num_5::H;
num_4 num_5::E;
class num_6 {
public:
num_5 high;
num_5 low;
static num_5 H;
static num_5 E;
num_6() {
high = low = num_5();
}
void out() {
high.out();
low.out();
}
void out1() {
num_5 t;
if (!show0)
{
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
else
{
out();
}
}
num_6 static mul(num_5& m, num_5& n) {
num_5 q1 = num_5::mul(m.low, n.low);
num_5 q2 = num_5::mul(m.high, n.low);
num_5 q3 = num_5::mul(n.high, m.low);
num_5 q4 = num_5::mul(m.high, n.high);
num_6 ans;
ans.low = q1;
num_5 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_5::H) {
ans.high.low.clearhigh();
ans.high.high = ans.high.high + num_5::E;
}
ans.high = ans.high + q4;
return ans;
}
num_6 operator+(num_5& b) {
num_6 ans = *this;
ans.low = ans.low + b;
if (ans.low > H) {
ans.low.clearhigh();
ans.high = ans.high + num_5::E;
}
return ans;
}
num_6 operator+(num_6& b) {
num_6 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_6& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_6& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_6& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s, int a) {
high.in(s, a + 512);
low.in(s, a);
}
};
num_5 num_6::H;
num_5 num_6::E;
class num_7 {
public:
num_6 high;
num_6 low;
static num_6 H;
static num_6 E;
num_7() {
high = low = num_6();
}
void out() {
high.out();
low.out();
}
void out1() {
num_6 t;
if (!show0)
{
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
else
{
out();
}
}
num_7 static mul(num_6& m, num_6& n) {
num_6 q1 = num_6::mul(m.low, n.low);
num_6 q2 = num_6::mul(m.high, n.low);
num_6 q3 = num_6::mul(n.high, m.low);
num_6 q4 = num_6::mul(m.high, n.high);
num_7 ans;
ans.low = q1;
num_6 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_6::H) {
ans.high.low.clearhigh();
ans.high.high = ans.high.high + num_6::E;
}
ans.high = ans.high + q4;
return ans;
}
num_7 operator+(num_6& b) {
num_7 ans = *this;
ans.low = ans.low + b;
if (ans.low > H) {
ans.low.clearhigh();
ans.high = ans.high + num_6::E;
}
return ans;
}
num_7 operator+(num_7& b) {
num_7 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_7& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_7& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_7& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s, int a) {
high.in(s, a + 1024);
low.in(s, a);
}
};
num_6 num_7::H;
num_6 num_7::E;
class num_8 {
public:
num_7 high;
num_7 low;
static num_7 H;
static num_7 E;
num_8() {
high = low = num_7();
}
void out() {
high.out();
low.out();
}
void out1() {
num_7 t;
if (high == t) {
low.out1();
}
else {
high.out1();
show0 = true;
low.out();
}
}
num_8 static mul(num_7& m, num_7& n) {
num_7 q1 = num_7::mul(m.low, n.low);
num_7 q2 = num_7::mul(m.high, n.low);
num_7 q3 = num_7::mul(n.high, m.low);
num_7 q4 = num_7::mul(m.high, n.high);
num_8 ans;
ans.low = q1;
num_7 temp = q2 + q3;
temp = temp + q1.high;
ans.low.high = temp.low;
ans.high.low = temp.high;
if (ans.high.low > num_7::H) {
ans.high.low.clearhigh();
ans.high.high = ans.high.high + num_7::E;
}
ans.high = ans.high + q4;
return ans;
}
num_8 operator+(num_7& b) {
num_8 ans = *this;
ans.low = ans.low + b;
if (ans.low > H) {
ans.low.clearhigh();
ans.high = ans.high + num_7::E;
}
return ans;
}
num_8 operator+(num_8& b) {
num_8 ans = *this;
ans = ans + b.low;
ans.high = ans.high + b.high;
return ans;
}
bool operator==(num_8& n) {
return(high == n.high && low == n.low);
}
bool operator>(num_8& n) {
if (high > n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
bool operator<(num_8& n) {
if (high < n.high) {
return true;
}
else if (high == n.high) {
if (low > n.low) {
return true;
}
}
return false;
}
void clearhigh() {
high.clearhigh();
}
void in(string& s, int a) {
high.in(s, a + 1024);
low.in(s, a);
}
};
num_7 num_8::H;
num_7 num_8::E;
void ini() {
num_1::H = 9999999999999999;
num_1::E = 1;
num_2::H.high = num_2::H.low = num_1::H;
num_2::E.low = 1;
num_3::H.high = num_3::H.low = num_2::H;
num_3::E.low = num_2::E;
num_4::H.high = num_4::H.low = num_3::H;
num_4::E.low = num_3::E;
num_5::H.high = num_5::H.low = num_4::H;
num_5::E.low = num_4::E;
num_6::H.high = num_6::H.low = num_5::H;
num_6::E.low = num_5::E;
num_7::H.high = num_7::H.low = num_6::H;
num_7::E.low = num_6::E;
num_8::H.high = num_8::H.low = num_7::H;
num_8::E.low = num_7::E;
}
int main()
{
ini();
cin >> z;
string s = z;
n = s.length();
for (int i = 0; i < n; i++) {
z[i] = s[n -1 - i];
}
num_7 p;
p.in(z, 0);
cin >> z;
s = z;
n = s.length();
for (int i = 0; i < n; i++) {
z[i] = s[n -1 - i];
}
num_7 q;
q.in(z, 0);
num_8 ans = num_8::mul(p, q);
ans.out1();
}
这里,我们在数字电路的视角下给出一种新奇的答案。我们知道在数电中,我们会把一些基础的芯片不断封装变成自相似的高级芯片。比如把全加器级联起来变成位数更高的全加器。这里,我们采用类似的思路。我们并不把注意力放在数组的开辟和大量的加法乘法的混合操作,而是把注意力放在这个问题上——如何扩展出cpp的原生类型的升级版。在本代码中,就是我们自定义的扩展类。首先,我们知道long long可以存放任意两个long相乘的结果,基于这一点,我们设置了num_1类来对应long long的升级版。我们设计了高位和低位,以及简单的求和求积以及进位法则。于是我们拿到了可以运算长度为long long的两倍的数据类型 num_1。注意,其实这里的类似于广义的BCD码,即存放的就是十进制数本身,只是采用了级联扩展的观念不断倍增位数。于是我们用H和E表示上一层的最大元和当前最小元。这两者的级联是显然的。注意到默认构造就是0,我们以及有了足够的信息。最后,我们充分运用了每一级底层的long没有被穷尽的事实,简化了加法与进位的难处。仔细阅读运算符重载的部分就会明白这一点方便在了哪里。不过这个思路下的做法其实用模板更加合适(而继承虽然可以增加代码复用率,但是不适合本做法,因为父类对象只有一个,而高低片(对象)一共是两个)。最后的最后是输出,由于没有采用全局数组,这里采用了全局变量show0来表示此后是否输出较高的0,实际上相当于数电芯片显示译码器的级联动态灭零端。
by Rainybunny @ 2022-12-26 08:12:19
你可以用 template <N>
的展开过程帮助你倍增,而不需要手写这么大一坨。
by Jerrlee✅ @ 2022-12-26 08:15:16
强大的
by aSunnyDay @ 2022-12-26 08:39:50
@wsfxk 实测
by aSunnyDay @ 2022-12-26 08:43:26
甚至连
该大佬直接
by Phartial @ 2022-12-26 08:46:16
@happydef 我草这么强大
by ExplodingKonjac @ 2022-12-26 08:50:10
其实这个就是采用分治的大整数相乘,时间复杂度可以做到
代码实现用 template
改改会更好。
by shstyle @ 2022-12-26 09:15:41
%%%%%%%%%%%%%%%%%
by ppip @ 2022-12-26 09:39:08
吐了,马蜂清奇,不尝试改 template
了
by Gaotianjia @ 2022-12-26 20:00:26
@Rainybunny 我知道,我也提到了可以用模板技术,但是考虑到只是复制黏贴当时也懒得引入模板参数了。后面我找个时间用模板实现。