提交记录 16108


用户 题目 状态 得分 用时 内存 语言 代码长度
ObsidianY 1002i. 【模板题】多项式乘法 Accepted 100 53.508 ms 13228 KB C++11 6.81 KB
提交时间 评测时间
2021-03-26 07:52:42 2021-03-26 07:52:46
// author: ycp | https://ycpedef.github.io
// #pragma GCC diagnostic error "-std=c++11"
// #pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdarg>
#include <cmath>
#define debug(x) cerr << #x << " = " << x << endl
#define debugf(...) fprintf(stderr, __VA_ARGS__)
#define wlog(fmt, ...) fprintf(stderr, "<%s:%d> " fmt "\n", __func__, __LINE__, ## __VA_ARGS__)
using namespace std;
template<class T> bool cmax(T &a, T b) { return b > a ? (a = b, 1) : 0; }
template<class T> bool cmin(T &a, T b) { return b < a ? (a = b, 1) : 0; }
template<class T> void read(T &a) {
    a = 0; char c = getchar(); int f = 0;
    while (!isdigit(c)) { f ^= c == '-',  c = getchar(); }
    while (isdigit(c)) { a = a * 10 + (c ^ 48),  c = getchar(); }
    a *= f ? -1 : 1;
}
struct Fastin {
    template<class T> Fastin& operator >> (T &x) { read(x); return *this; }
} fastin;

#include <utility>
#include <cstring>
#include <cstdio>
#include <cctype>

namespace poly {

using u64 = unsigned long long;
using std::forward;

const u64 mod = 998244353;
const u64 G = 3;

int *log2 = nullptr, *rev = nullptr, rev_limit = 1;
u64 **w;

inline u64 power(u64 a, int b);
inline void swap(u64 &a, u64 &b);
inline void reverse(u64* p1, u64* p2);
inline void read(u64 &a);
inline void init(int n);

struct poly_t {
    u64 *src; int deg;

    inline void read(int);
    inline void print(int) const;

    poly_t(int); poly_t(int, int);
    poly_t(const poly_t &); poly_t(poly_t &&);
    ~poly_t() { delete[] src; }
    void resize(int);
    void copy(const poly_t &);
    poly_t& operator = (const poly_t &);
    poly_t& operator = (poly_t &&);
    u64& operator [] (const int &x) { return src[x]; }
    u64 operator [] (const int &x) const { return src[x]; }

    inline void NTT(int);
    inline void DFT() { return NTT(1); }
    inline void IDFT() { return NTT(-1); }
};

// -------------------------- poly_t start ----------------------------

#define cp(dest, src, cnt) memcpy(dest, src, cnt * sizeof(u64))
inline void poly_t::copy(const poly_t &p) {
    deg = p.deg, src = new u64[deg](); cp(src, p.src, deg);
}
void poly_t::resize(int c) {
    if (c <= deg) return;
    u64 *pre = src; src = new u64[c](); cp(src, pre, deg);
    deg = c, delete[] pre;
}
#undef cp

poly_t::poly_t(int siz) { wlog("new");deg = siz; src = new u64[deg](); }
poly_t::poly_t(int siz, int n) { wlog("new");deg = siz; src = new u64[deg](); read(n); }
poly_t::poly_t(const poly_t& p) { wlog("copy");copy(p); }
poly_t::poly_t(poly_t &&p) { wlog("move");deg = p.deg, src = p.src, p.src = nullptr; }
poly_t& poly_t::operator = (const poly_t& p) { wlog("copy");
    if (this != &p) { delete[] src; copy(p); }
    return *this;
}
poly_t& poly_t::operator = (poly_t &&p) { wlog("move");
    if (this != &p) {
        delete[] src; deg = p.deg, src = p.src, p.src = nullptr;
    }
    return *this;
}

inline void poly_t::read(int n) {
    for (int i = 0; i < n; i++) { poly::read(src[i]); }
}
inline void poly_t::print(int n) const {
    for (int i = 0; i < n; i++) { printf("%llu ", src[i]); } putchar('\n');
}

inline void poly_t::NTT(int mode) {
    for (int i = 0; i < deg; i++) {
        if (i < rev[i]) poly::swap(src[i], src[rev[i]]);
    }

    u64 *f = src, *g, t1, t2;
    for (int k = 1, i, j, l, x = 1; (k << 1) <= deg; k <<= 1, x++) {
        l = k << 1;
        for (i = 0; i < deg; i += l) {
            for (j = i, g = w[x]; j < i + k; j++, g++) {
                t1 = f[j], t2 = (((*g) * f[j | k])) % mod;
                f[j] = t1 + t2;
                f[j | k] = t1 - t2 + mod;
            }
        }
        if (k & (1 << 16)) {
            for (int i = 0; i < deg; i++) {
                f[i] %= mod;
            }
        }
    }

    if (mode < 0) {
        poly::reverse(f + 1, f + deg);
        u64 inv = power(deg, mod - 2);
        for (int i = 0; i < deg; i++) f[i] *= inv;
    }
    for (int i = 0; i < deg; i++) f[i] %= mod;
}

template<typename T>
poly_t inv(T &&p) {
    poly_t f(forward<T>(p));
    return f;
}

template<typename T>
poly_t ln(T &&p) {
    poly_t f(forward<T>(p));
    return f;
}

template<typename T>
poly_t exp(T &&p) {
    poly_t f(forward<T>(p));
    return f;
}

template<typename T1, typename T2>
poly_t operator * (T1 &&p1, T2 &&p2) {
    poly_t a(forward<T1>(p1)), b(forward<T2>(p2));
    //wlog("DFT");
    a.DFT(), b.DFT();
    poly_t c(a.deg);
    for (int i = 0; i < c.deg; i++) (c[i] = a[i] * b[i]) %= mod;
    //wlog("IDFT");
    c.IDFT();
    //wlog("complete");
    return c;
}

//------------------------- poly_t end -------------------------------

inline u64 power(u64 a, int b) {
    u64 res = 1;
    //debugf("power(%llu, %d) ", a, b);
    while (b) { if (b & 1) (res *= a) %= mod; b >>= 1, (a *= a) %= mod; }
    //debugf("= %llu\n", res);
    return res;
}
inline void swap(u64 &a, u64 &b) { u64 t = a; a = b, b = t; }

inline void reverse(u64* p1, u64* p2) { p2--; while (p1 < p2) { swap(*p1, *p2), p1++, p2--; } }

inline void read(u64 &a) {
    a = 0; char c = getchar(); int f = 0;
    while (!isdigit(c)) { f ^= c == '-',  c = getchar(); }
    while (isdigit(c)) { a = a * 10 + (c ^ 48),  c = getchar(); }
    a *= f ? -1 : 1;
}

inline void init(int n = 1e6) {
    //delete[] poly::log2, poly::log2 = new int[n + 10]();
    //poly::log2[0] = -1;
    //for (int i = 1; i <= n; i++) {
    //    poly::log2[i] = poly::log2[i >> 1] + 1;
    //}
    delete[] rev, rev = new int[n + 10]();
    int log_limit = 1;
    while ((rev_limit << 1) <= n) rev_limit <<= 1, log_limit++;
    //debug(rev_limit);
    for (int i = 0; i < rev_limit; i++) {
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * (n >> 1));
    }
    w = new u64*[log_limit + 10]();
    for (int i = 0; i < log_limit; i++) w[i] = new u64[1 << i]();
    for (int i = 0, l; i < log_limit; i++) {    
        l = (1 << i);
        u64 g0 = power(G, (mod - 1) / l), *p = w[i];
        *p = 1;
        //debug(g0);
        for (int j = 1; j < l; j++, p++) { *(p + 1) = *p * g0 % mod; }
        //for (int j = 0; j < l; j++) {
        //    debugf("w[%d][%d] = %llu\n", i, j, w[i][j]);
        //}
    }
}

} // namespace poly


using poly::poly_t;

int n, m;

struct io_t {
#define gc() (s == t && (t = (s = in) + fread(in, 1, SIZ, stdin), s == t) ? EOF : *s++)
    static const int SIZ = 1 << 25;
    char in[SIZ], *s = in, *t = in;
    template<typename T>
    io_t& operator>>(T& x) {
        x = 0;
        char c = gc();
        while (c < '0') c = gc();
        while (c >= '0') x = x * 10 + c - 48, c = gc();
        return *this;
    }
} io;

int main() {
    //freopen("poly.in", "r", stdin);
    //freopen("poly.out", "w", stdout);
    io >> n >> m;
    int len = 1 << (unsigned)(std::ceil(log2(n + m + 1)));
    poly::init(len);
    poly_t a(len);
    for (int i = 0; i <= n; i++) io >> a[i];
    poly_t b(len);
    for (int i = 0; i <= m; i++) io >> b[i];
    (std::move(a) * std::move(b)).print(n + m + 1);
    return 0;
}


CompilationN/AN/ACompile OKScore: N/A

Subtask #1 Testcase #141.13 us44 KBAcceptedScore: 0

Subtask #1 Testcase #252.692 ms12 MB + 860 KBAcceptedScore: 100

Subtask #1 Testcase #324.29 ms6 MB + 8 KBAcceptedScore: 0

Subtask #1 Testcase #424.456 ms5 MB + 1020 KBAcceptedScore: 0

Subtask #1 Testcase #541.75 us44 KBAcceptedScore: 0

Subtask #1 Testcase #640.36 us44 KBAcceptedScore: 0

Subtask #1 Testcase #741.28 us44 KBAcceptedScore: 0

Subtask #1 Testcase #847.346 ms12 MB + 528 KBAcceptedScore: 0

Subtask #1 Testcase #947.357 ms12 MB + 528 KBAcceptedScore: 0

Subtask #1 Testcase #1042.233 ms12 MB + 192 KBAcceptedScore: 0

Subtask #1 Testcase #1152.594 ms12 MB + 940 KBAcceptedScore: 0

Subtask #1 Testcase #1253.508 ms11 MB + 820 KBAcceptedScore: 0

Subtask #1 Testcase #1339.34 us44 KBAcceptedScore: 0


Judge Duck Online | 评测鸭在线
Server Time: 2024-05-04 01:35:21 | Loaded in 2 ms | Server Status
个人娱乐项目,仅供学习交流使用