po167_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub potato167/po167_library

:heavy_check_mark: test/fps/online_fps.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod"


#include "../../fps/FPS_online_convolution.hpp"


#include <iostream>
using mint = atcoder::modint998244353;
int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N, M;
    std::cin >> N >> M;
    int X = N + M - 1;
    std::vector<int> A(X), B(X);
    for (int i = 0; i < N; i++) std::cin >> A[i];
    for (int i = 0; i < M; i++) std::cin >> B[i];
    po167::FPS_online_convolution<mint> oc;
    for (int i = 0; i < X; i++){
        if (i) std::cout << " ";
        std::cout << oc.query(A[i], B[i]).val();
    }
    std::cout << "\n";
}
#line 1 "test/fps/online_fps.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/convolution_mod"


#line 2 "fps/FPS_online_convolution.hpp"
#include <atcoder/convolution>

namespace po167{
template<class T>
struct FPS_online_convolution{
    std::vector<T> f, g, h, iz;
    std::vector<std::vector<T>> f_inv, g_inv;
    int p;
    FPS_online_convolution() : f(0), g(0), h(0), iz(0), p(0){}
    T query(T fi, T gi){
        if (p == 0){
            f = {fi};
            g = {gi};
            h = {fi * gi};
            return h[p++];
        }
        int z = 0;
        while ((p & (1 << z)) == 0) z++;
        if (p == (1 << z)){
            f.resize(p * 2, 0);
            g.resize(p * 2, 0);
            h.resize(p * 2, 0);
        }
        f[p] = fi;
        g[p] = gi;
        int l = p - (1 << z);
        int m = p;
        int r = p + (1 << z);
        // [l, m) -> [m, r)
        std::vector<T> tmp3(r - l);
        if (l == 0){
            f_inv.push_back({});
            g_inv.push_back({});
            iz.push_back((T)(1) / (T)(r - l));
        }
        for (int rp = 0; rp < 2; rp++){
            std::swap(f, g);
            std::swap(f_inv, g_inv);
            if (l == 0 && rp == 1) break;
            std::vector<T> tmp1(r - l), tmp2(r - l);
            for (int i = l; i < m; i++){
                tmp1[i - l] = f[i];
            }
            atcoder::internal::butterfly(tmp1);
            if (l == 0) {
                for (int i = 0; i < r - l; i++) {
                    if (i == 0) continue;
                    if (m <= i) break;
                    tmp2[i] = g[i];
                }
                atcoder::internal::butterfly(tmp2);
            }
            else{
                if (g_inv[z].empty()){
                    g_inv[z].resize((1 << (z + 1)));
                    for (int i = 0; i < (1 << (z + 1)); i++){
                        if (i) g_inv[z][i] = g[i];
                        else g_inv[z][i] = 0;
                    }
                    atcoder::internal::butterfly(g_inv[z]);
                }
                tmp2 = g_inv[z];
            }
            for (int i = 0; i < r - l; i++) tmp3[i] += tmp1[i] * tmp2[i];
        }
        atcoder::internal::butterfly_inv(tmp3);
        for (int i = m; i < r; i++) h[i] += tmp3[i - l] * iz[z];
        h[p] += f[0] * g[p];
        h[p] += f[p] * g[0];
        return h[p++];
    }
};
}
#line 5 "test/fps/online_fps.test.cpp"


#include <iostream>
using mint = atcoder::modint998244353;
int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N, M;
    std::cin >> N >> M;
    int X = N + M - 1;
    std::vector<int> A(X), B(X);
    for (int i = 0; i < N; i++) std::cin >> A[i];
    for (int i = 0; i < M; i++) std::cin >> B[i];
    po167::FPS_online_convolution<mint> oc;
    for (int i = 0; i < X; i++){
        if (i) std::cout << " ";
        std::cout << oc.query(A[i], B[i]).val();
    }
    std::cout << "\n";
}
Back to top page