关于高精度

虽然感觉没什么用,但是不知道为什么最近洛谷给我随机跳了好几道要高精度的 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;
}
posted @ 2025-03-25 21:25  jxy2012  阅读(31)  评论(0)    收藏  举报
//雪花飘落效果