結果

問題 No.1068 #いろいろな色 / Red and Blue and more various colors (Hard)
ユーザー maspymaspy
提出日時 2020-05-29 22:20:29
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 690 ms / 3,500 ms
コード長 5,575 bytes
コンパイル時間 2,205 ms
コンパイル使用メモリ 209,804 KB
実行使用メモリ 53,992 KB
最終ジャッジ日時 2024-04-23 23:08:40
合計ジャッジ時間 16,316 ms
ジャッジサーバーID
(参考情報)
judge3 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 1 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 16 ms
5,376 KB
testcase_04 AC 11 ms
5,376 KB
testcase_05 AC 14 ms
5,376 KB
testcase_06 AC 11 ms
5,376 KB
testcase_07 AC 9 ms
5,376 KB
testcase_08 AC 12 ms
5,376 KB
testcase_09 AC 13 ms
5,376 KB
testcase_10 AC 6 ms
5,376 KB
testcase_11 AC 9 ms
5,376 KB
testcase_12 AC 6 ms
5,376 KB
testcase_13 AC 670 ms
53,864 KB
testcase_14 AC 675 ms
53,864 KB
testcase_15 AC 673 ms
53,732 KB
testcase_16 AC 672 ms
53,860 KB
testcase_17 AC 672 ms
53,860 KB
testcase_18 AC 685 ms
53,864 KB
testcase_19 AC 678 ms
53,776 KB
testcase_20 AC 679 ms
53,948 KB
testcase_21 AC 687 ms
53,884 KB
testcase_22 AC 680 ms
53,992 KB
testcase_23 AC 675 ms
53,732 KB
testcase_24 AC 687 ms
53,856 KB
testcase_25 AC 690 ms
53,856 KB
testcase_26 AC 686 ms
53,784 KB
testcase_27 AC 684 ms
53,988 KB
testcase_28 AC 677 ms
53,736 KB
testcase_29 AC 665 ms
53,864 KB
testcase_30 AC 666 ms
53,856 KB
testcase_31 AC 2 ms
5,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

template <typename T, T MOD = 1000000007>
struct Mint
{
    static constexpr T mod = MOD;
    T v;
    Mint() : v(0) {}
    Mint(signed v) : v(v) {}
    Mint(long long t)
    {
        v = t % MOD;
        if (v < 0)
            v += MOD;
    }

    Mint pow(long long k)
    {
        Mint res(1), tmp(v);
        while (k)
        {
            if (k & 1)
                res *= tmp;
            tmp *= tmp;
            k >>= 1;
        }
        return res;
    }

    static Mint add_identity() { return Mint(0); }
    static Mint mul_identity() { return Mint(1); }

    Mint inv() { return pow(MOD - 2); }

    Mint &operator+=(Mint a)
    {
        v += a.v;
        if (v >= MOD)
            v -= MOD;
        return *this;
    }
    Mint &operator-=(Mint a)
    {
        v += MOD - a.v;
        if (v >= MOD)
            v -= MOD;
        return *this;
    }
    Mint &operator*=(Mint a)
    {
        v = 1LL * v * a.v % MOD;
        return *this;
    }
    Mint &operator/=(Mint a) { return (*this) *= a.inv(); }

    Mint operator+(Mint a) const { return Mint(v) += a; }
    Mint operator-(Mint a) const { return Mint(v) -= a; }
    Mint operator*(Mint a) const { return Mint(v) *= a; }
    Mint operator/(Mint a) const { return Mint(v) /= a; }

    Mint operator-() const { return v ? Mint(MOD - v) : Mint(v); }

    bool operator==(const Mint a) const { return v == a.v; }
    bool operator!=(const Mint a) const { return v != a.v; }
    bool operator<(const Mint a) const { return v < a.v; }

    static Mint comb(long long n, int k)
    {
        Mint num(1), dom(1);
        for (int i = 0; i < k; i++)
        {
            num *= Mint(n - i);
            dom *= Mint(i + 1);
        }
        return num / dom;
    }
};
template <typename T, T MOD>
constexpr T Mint<T, MOD>::mod;
template <typename T, T MOD>
ostream &operator<<(ostream &os, Mint<T, MOD> m)
{
    os << m.v;
    return os;
}

constexpr int bmds(int x)
{
    const int v[] = {1012924417, 924844033, 998244353,
                     897581057, 645922817};
    return v[x];
}
constexpr int brts(int x)
{
    const int v[] = {5, 5, 3, 3, 3};
    return v[x];
}

template <int X>
struct NTT
{
    static constexpr int md = bmds(X);
    static constexpr int rt = brts(X);
    using M = Mint<int, md>;
    vector<vector<M>> rts, rrts;

    void ensure_base(int n)
    {
        if ((int)rts.size() >= n)
            return;
        rts.resize(n);
        rrts.resize(n);
        for (int i = 1; i < n; i <<= 1)
        {
            if (!rts[i].empty())
                continue;
            M w = M(rt).pow((md - 1) / (i << 1));
            M rw = w.inv();
            rts[i].resize(i);
            rrts[i].resize(i);
            rts[i][0] = M(1);
            rrts[i][0] = M(1);
            for (int k = 1; k < i; k++)
            {
                rts[i][k] = rts[i][k - 1] * w;
                rrts[i][k] = rrts[i][k - 1] * rw;
            }
        }
    }

    void ntt(vector<M> &as, bool f)
    {
        int n = as.size();
        assert((n & (n - 1)) == 0);
        ensure_base(n);

        for (int i = 0, j = 1; j + 1 < n; j++)
        {
            for (int k = n >> 1; k > (i ^= k); k >>= 1)
                ;
            if (i > j)
                swap(as[i], as[j]);
        }

        for (int i = 1; i < n; i <<= 1)
        {
            for (int j = 0; j < n; j += i * 2)
            {
                for (int k = 0; k < i; k++)
                {
                    M z = as[i + j + k] * (f ? rrts[i][k] : rts[i][k]);
                    as[i + j + k] = as[j + k] - z;
                    as[j + k] += z;
                }
            }
        }

        if (f)
        {
            M tmp = M(n).inv();
            for (int i = 0; i < n; i++)
                as[i] *= tmp;
        }
    }

    vector<M> multiply(vector<M> as, vector<M> bs)
    {
        int need = as.size() + bs.size() - 1;
        int sz = 1;
        while (sz < need)
            sz <<= 1;
        as.resize(sz, M(0));
        bs.resize(sz, M(0));

        ntt(as, 0);
        ntt(bs, 0);
        for (int i = 0; i < sz; i++)
            as[i] *= bs[i];
        ntt(as, 1);

        as.resize(need);
        return as;
    }

    vector<int> multiply(vector<int> as, vector<int> bs)
    {
        vector<M> am(as.size()), bm(bs.size());
        for (int i = 0; i < (int)am.size(); i++)
            am[i] = M(as[i]);
        for (int i = 0; i < (int)bm.size(); i++)
            bm[i] = M(bs[i]);
        vector<M> cm = multiply(am, bm);
        vector<int> cs(cm.size());
        for (int i = 0; i < (int)cs.size(); i++)
            cs[i] = cm[i].v;
        return cs;
    }
};

template <int X>
constexpr int NTT<X>::md;
template <int X>
constexpr int NTT<X>::rt;

signed main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);
    int N, Q;
    cin >> N >> Q;
    NTT<2> ntt;
    using M = decltype(ntt)::M;
    vector<vector<M>> polys;
    for (int i = 0; i < N; i++)
    {
        ll x;
        cin >> x;
        vector<M> v;
        v.push_back(x - 1);
        v.push_back(1);
        polys.push_back(v);
    }
    int L = N;
    while (L >= 2)
    {
        for (int i = 1; i < L; i += 2)
        {
            polys[i - 1] = ntt.multiply(polys[i - 1], polys[i]);
        }
        L = (L + 1) / 2;
        for (int i = 0; i < L; i++)
        {
            polys[i] = polys[2 * i];
        }
    }
    auto P = polys[0];
    for (int i = 0; i < Q; i++)
    {
        int d;
        cin >> d;
        cout << P[d].v << endl;
    }
}
0