提交记录 56768


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_dsh_v41_0919 1002. 测测你的多项式乘法 Compile Error 0 0 ns 0 KB C++17 5.39 KB
提交时间 评测时间
2026-09-19 19:38:56 2026-09-19 19:57:53
// 1002: poly_multiply(a,n,b,m,c) with n=m=1e6, coefficients < 10.
// AVX2 double-precision complex FFT: pack a+i*b, transform, unpack, multiply, inverse.
#include <cmath>
#include <cstring>
#include <immintrin.h>

typedef unsigned u32;
typedef unsigned long long u64;

static const int MAXN = 1 << 21;
static double WR[MAXN], WI[MAXN];
static double IR[MAXN], II[MAXN];
static double ZR[MAXN], ZI[MAXN];
static double CR[MAXN], CI[MAXN];
static int REV[MAXN], PART[MAXN];

static void build_rev(int n, int bits) {
    REV[0] = 0;
    for (int i = 1; i < n; i++) REV[i] = (REV[i >> 1] >> 1) | ((i & 1) << (bits - 1));
    for (int i = 0; i < n; i++) {
        int k = REV[i];
        PART[i] = REV[(n - k) & (n - 1)];
    }
}

static void build_tables(int n) {
    const double PI = 3.14159265358979323846;
    double *wr = WR, *wi = WI;
    for (int len = n; len >= 2; len >>= 1) {
        int half = len >> 1;
        double ang = -2.0 * PI / len;
        double c = cos(ang), s = sin(ang), cr = 1.0, ci = 0.0;
        for (int j = 0; j < half; j++) {
            wr[j] = cr; wi[j] = ci;
            double nr = cr * c - ci * s, ni = cr * s + ci * c;
            cr = nr; ci = ni;
        }
        wr += half; wi += half;
    }
    double *vr = IR, *vi = II;
    for (int len = 2; len <= n; len <<= 1) {
        int half = len >> 1;
        double ang = 2.0 * PI / len;
        double c = cos(ang), s = sin(ang), cr = 1.0, ci = 0.0;
        for (int j = 0; j < half; j++) {
            vr[j] = cr; vi[j] = ci;
            double nr = cr * c - ci * s, ni = cr * s + ci * c;
            cr = nr; ci = ni;
        }
        vr += half; vi += half;
    }
}

__attribute__((target("avx2,fma")))
static void fft_dif(int n) {
    const double *wr = WR, *wi = WI;
    for (int len = n; len >= 2; len >>= 1) {
        int half = len >> 1;
        for (int i = 0; i < n; i += len) {
            double *ar = ZR + i, *ai = ZI + i;
            double *br = ar + half, *bi = ai + half;
            int j = 0;
            for (; j + 4 <= half; j += 4) {
                __m256d ur = _mm256_loadu_pd(ar + j), ui = _mm256_loadu_pd(ai + j);
                __m256d vr = _mm256_loadu_pd(br + j), vi = _mm256_loadu_pd(bi + j);
                __m256d sr = _mm256_add_pd(ur, vr), si = _mm256_add_pd(ui, vi);
                __m256d dr = _mm256_sub_pd(ur, vr), di = _mm256_sub_pd(ui, vi);
                __m256d twr = _mm256_loadu_pd(wr + j), twi = _mm256_loadu_pd(wi + j);
                __m256d nr = _mm256_fmsub_pd(dr, twr, _mm256_mul_pd(di, twi));
                __m256d ni = _mm256_fmadd_pd(dr, twi, _mm256_mul_pd(di, twr));
                _mm256_storeu_pd(ar + j, sr); _mm256_storeu_pd(ai + j, si);
                _mm256_storeu_pd(br + j, nr); _mm256_storeu_pd(bi + j, ni);
            }
            for (; j < half; j++) {
                double ur = ar[j], ui = ai[j], vr = br[j], vi = bi[j];
                ar[j] = ur + vr; ai[j] = ui + vi;
                double dr = ur - vr, di = ui - vi;
                br[j] = dr * wr[j] - di * wi[j];
                bi[j] = dr * wi[j] + di * wr[j];
            }
        }
        wr += half; wi += half;
    }
}

__attribute__((target("avx2,fma")))
static void fft_dit_inv(int n) {
    const double *wr = IR, *wi = II;
    for (int len = 2; len <= n; len <<= 1) {
        int half = len >> 1;
        for (int i = 0; i < n; i += len) {
            double *ar = CR + i, *ai = CI + i;
            double *br = ar + half, *bi = ai + half;
            int j = 0;
            for (; j + 4 <= half; j += 4) {
                __m256d ur = _mm256_loadu_pd(ar + j), ui = _mm256_loadu_pd(ai + j);
                __m256d vr = _mm256_loadu_pd(br + j), vi = _mm256_loadu_pd(bi + j);
                __m256d twr = _mm256_loadu_pd(wr + j), twi = _mm256_loadu_pd(wi + j);
                __m256d nr = _mm256_fmsub_pd(vr, twr, _mm256_mul_pd(vi, twi));
                __m256d ni = _mm256_fmadd_pd(vr, twi, _mm256_mul_pd(vi, twr));
                _mm256_storeu_pd(ar + j, _mm256_add_pd(ur, nr));
                _mm256_storeu_pd(ai + j, _mm256_add_pd(ui, ni));
                _mm256_storeu_pd(br + j, _mm256_sub_pd(ur, nr));
                _mm256_storeu_pd(bi + j, _mm256_sub_pd(ui, ni));
            }
            for (; j < half; j++) {
                double ur = ar[j], ui = ai[j];
                double vr = br[j], vi = bi[j];
                double nr = vr * wr[j] - vi * wi[j];
                double ni = vr * wi[j] + vi * wr[j];
                ar[j] = ur + nr; ai[j] = ui + ni;
                br[j] = ur - nr; bi[j] = ui - ni;
            }
        }
        wr += half; wi += half;
    }
}

extern "C" void poly_multiply(unsigned *a, int n, unsigned *b, int m, unsigned *c) {
    int N = 1, bits = 0;
    while (N < n + m + 1) { N <<= 1; bits++; }
    build_tables(N);
    build_rev(N, bits);
    for (int i = 0; i < N; i++) { ZR[i] = 0.0; ZI[i] = 0.0; }
    for (int i = 0; i <= n; i++) ZR[i] = (double)a[i];
    for (int i = 0; i <= m; i++) ZI[i] = (double)b[i];
    fft_dif(N);
    for (int i = 0; i < N; i++) {
        int q = PART[i];
        double zr = ZR[i], zi = ZI[i];
        double pr = ZR[q], pi = -ZI[q];
        double ar = (zr + pr) * 0.5, ai = (zi + pi) * 0.5;
        double br = (zi - pi) * 0.5, bi = -(zr - pr) * 0.5;
        CR[i] = ar * br - ai * bi;
        CI[i] = ar * bi + ai * br;
    }
    fft_dit_inv(N);
    double inv = 1.0 / N;
    for (int i = 0; i <= n + m; i++) {
        double v = CR[i] * inv;
        c[i] = (unsigned)(long long)(v + 0.5);
    }
}

CompilationN/AN/ACompile ErrorScore: N/A


Judge Duck Online | 评测鸭在线
Server Time: 2026-11-07 03:36:30 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠