(高精度乘法)A*B problem

https://www.luogu.org/problemnew/show/P1303
数论优化的fft

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e6 + 5;
const int P = 998244353;
inline int qpow(int d, int z)
{
  int ans=1;
  for(; z; z >>= 1, d = 1ll * d * d % P)
    if(z & 1) ans = 1ll * ans * d % P;
  return ans;
}
int r[maxn];
void ntt(int *x, int lim, int opt) {
    register int i, j, k, m, gn, g, tmp;
    for(i = 0; i < lim; i++)
        if(r[i] < i) swap(x[i], x[r[i]]);
    for(m = 2; m <= lim; m <<= 1) {
        k = m >> 1;
        gn = qpow(3, (P - 1) / m);
        for(i = 0; i < lim; i += m) {
            g = 1;
            for(j = 0; j < k; j++, g = 1ll * g * gn % P) {
                tmp = 1ll * x[i + j + k] * g % P;
                x[i + j + k] = (x[i + j] - tmp + P) % P;
                x[i + j] = (x[i + j] + tmp) % P;
            }
        }
    }
    if(opt == -1) {
        reverse(x + 1, x + lim);
        register int inv = qpow(lim, P - 2);
        for(i = 0; i < lim; i++) 
            x[i] = 1ll * x[i] * inv % P;
    }
}
int A[maxn], B[maxn], C[maxn];
char a[maxn], b[maxn];

int main()
{
    register int i, lim(1), n;
    scanf("%s", &a);
    n = strlen(a);
    for(i = 0; i < n; i++) A[i] = a[n - i - 1] - '0';
    while(lim < (n << 1)) lim <<= 1;
    scanf("%s", &b);
    n = strlen(b);
    for(i = 0; i < n; i++) B[i] = b[n - i - 1] - '0';
    while(lim < (n << 1)) lim <<= 1;
    for(i = 0; i < lim; i++) r[i] = (i & 1) * (lim >> 1) + (r[i >> 1] >> 1);
    ntt(A, lim, 1);
    ntt(B, lim, 1);
    for(i = 0; i < lim; i++) C[i] = 1ll * A[i] * B[i] % P;
    ntt(C, lim, -1);
    int len(0);
    for(i = 0; i < lim; i++) {
        if(C[i] >= 10) len = i + 1, C[i + 1] += C[i] / 10, C[i] %= 10;
        if(C[i]) len = max(len, i);
    }
    while(C[len] >= 10) C[len + 1] += C[len] / 10, C[len] %= 10, len++;
    for(i = len; ~i; i--) putchar(C[i] + '0');
    puts("");
    // system("pause");
}

看花费时间,应该比数组模拟优秀一些

猜你喜欢

转载自blog.csdn.net/weixin_40588429/article/details/84097886
今日推荐