关于高精度
虽然感觉没什么用,但是不知道为什么最近洛谷给我随机跳了好几道要高精度的 dp 题,每次都打太烦了,在这里放几个板子吧。
加法
string add(string x, string y) {
reverse(x.begin(), x.end());
reverse(y.begin(), y.end());
while (x.size() < y.size()) x.push_back('0');
while (y.size() < x.size()) y.push_back('0');
string res;
int c = 0;
for (int i = 0; i < x.size(); i++) {
res.push_back((x[i] - '0' + y[i] - '0' + c) % 10 + '0');
c = max(0, (x[i] - '0' + y[i] - '0' + c) / 10);
}
if (c != 0) res.push_back(c + '0');
reverse(res.begin(), res.end());
return res;
}
就是模拟,没什么好说的。
减法
感觉不怎么用,等到用了再写吧。
乘法
高精度乘单精度
因为我比较懒,正常的写法太烦了,就写了个基于加法的。
类似快速幂,计算大数 \(x\) 和较小的 \(y\) 的乘积时,考虑将 \(y\) 二进制拆分。
好写好调。
string mul(string x, int y) {
string res = "0";
while (y) {
if (y & 1) res = add(res, x);
y >>= 1;
x = add(x, x);
}
return res;
}
高精度乘高精度
太烦了,直接 fft 吧。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 4000005;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
struct Complex {
double x, y;
Complex(double _x = 0.0, double _y = 0.0) {
x = _x;
y = _y;
}
Complex operator-(const Complex &b) const {
return Complex(x - b.x, y - b.y);
}
Complex operator+(const Complex &b) const {
return Complex(x + b.x, y + b.y);
}
Complex operator*(const Complex &b) const {
return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
}
};
void change(Complex y[], int len) {
for (int i = 1, j = len / 2, k; i < len - 1; i++) {
if (i < j) swap(y[i], y[j]);
k = len / 2;
while (j >= k) {
j = j - k;
k = k / 2;
}
if (j < k) j += k;
}
}
void fft(Complex y[], int len, int on) {
change(y, len);
for (int h = 2; h <= len; h <<= 1) {
Complex wn(cos(2 * PI / h), sin(on * 2 * PI / h));
for (int j = 0; j < len; j += h) {
Complex w(1, 0);
for (int k = j; k < j + h / 2; k++) {
Complex u = y[k];
Complex t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
}
if (on == -1) {
for (int i = 0; i < len; i++) {
y[i].x /= len;
}
}
}
Complex x1[N], x2[N];
char str1[N], str2[N];
int sum[N];
int main() {
scanf("%s%s", str1, str2);
int len1 = strlen(str1);
int len2 = strlen(str2);
int len = 1;
while (len < len1 * 2 || len < len2 * 2) len <<= 1;
for (int i = 0; i < len1; i++) x1[i] = Complex(str1[len1 - 1 - i] - '0', 0);
for (int i = len1; i < len; i++) x1[i] = Complex(0, 0);
for (int i = 0; i < len2; i++) x2[i] = Complex(str2[len2 - 1 - i] - '0', 0);
for (int i = len2; i < len; i++) x2[i] = Complex(0, 0);
fft(x1, len, 1);
fft(x2, len, 1);
for (int i = 0; i < len; i++) x1[i] = x1[i] * x2[i];
fft(x1, len, -1);
for (int i = 0; i < len; i++) sum[i] = int(x1[i].x + 0.5);
for (int i = 0; i < len; i++) {
sum[i + 1] += sum[i] / 10;
sum[i] %= 10;
}
len = len1 + len2 - 1;
while (sum[len] == 0 && len > 0) len--;
for (int i = len; i >= 0; i--) printf("%c", sum[i] + '0');
printf("\n");
return 0;
}
除法
int a[N], b[N];
int c[N];
bool check(int* a, int* b, int len) {
if (a[len] > 0) return true;
for (int i = len - 1; i >= 0; i--) {
if (a[i] > b[i])
return true;
else if (a[i] < b[i])
return false;
}
return true;
}
string div(string x, string y) {
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
memset(c, 0, sizeof c);
int lena = x.size(), lenb = y.size();
int len = lena - lenb;
for (int i = 0; i < lena; i++) a[i] = x[lena - 1 - i] - '0';
for (int i = 0; i < lenb; i++) b[i] = y[lenb - 1 - i] - '0';
for (int i = lena - lenb; i >= 0; i--) {
while (check(a + i, b, lenb)) {
c[i]++;
for (int j = 0; j <= lenb - 1; j++) {
if (a[i + j] < b[j]) {
a[i + j + 1]--;
a[i + j] += 10;
}
a[i + j] -= b[j];
}
}
}
while (a[lena] == 0 && lena > 0) lena--;
while (c[len] == 0 && len > 0) len--;
string res;
for (int i = len; i >= 0; i--) res.push_back(c[i] + '0');
if (len < 0) res = "0";
return res;
}

浙公网安备 33010602011771号