結果

問題 No.2566 美しい整数列
ユーザー onkryoonkryo
提出日時 2023-12-04 23:12:53
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 132 ms / 2,000 ms
コード長 35,884 bytes
コンパイル時間 3,976 ms
コンパイル使用メモリ 242,316 KB
実行使用メモリ 20,608 KB
最終ジャッジ日時 2024-09-26 23:19:48
合計ジャッジ時間 7,603 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,248 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 2 ms
5,376 KB
testcase_04 AC 130 ms
20,480 KB
testcase_05 AC 132 ms
20,480 KB
testcase_06 AC 68 ms
7,936 KB
testcase_07 AC 64 ms
7,936 KB
testcase_08 AC 62 ms
7,936 KB
testcase_09 AC 63 ms
8,064 KB
testcase_10 AC 64 ms
7,936 KB
testcase_11 AC 92 ms
11,008 KB
testcase_12 AC 88 ms
11,008 KB
testcase_13 AC 87 ms
11,008 KB
testcase_14 AC 97 ms
11,008 KB
testcase_15 AC 84 ms
11,136 KB
testcase_16 AC 112 ms
20,480 KB
testcase_17 AC 117 ms
20,480 KB
testcase_18 AC 121 ms
20,608 KB
testcase_19 AC 77 ms
14,720 KB
testcase_20 AC 114 ms
19,200 KB
testcase_21 AC 118 ms
19,584 KB
testcase_22 AC 74 ms
13,696 KB
testcase_23 AC 91 ms
17,920 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include "bits/stdc++.h"
#include <numeric>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

// clang-format off
/* accelration */
// 高速バイナリ生成
#pragma GCC target("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
// cin cout の結びつけ解除, stdioと同期しない(入出力非同期化)
// cとstdの入出力を混在させるとバグるので注意
struct Fast { Fast() { std::cin.tie(0); ios::sync_with_stdio(false); } } fast;


using mint9 = modint998244353;

/* alias */
using ull = unsigned long long;
using ll = long long;
using vi = vector<int>;
using vl = vector<long>;
using vll = vector<long long>;
using vvi = vector<vi>;
using vvl = vector<vl>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vd = vector<double>;
using vs = vector<string>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;
using vm = vector<mint9>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
using vs = vector<string>;

/* define short */
#define pb push_back
// #define mp make_pair
#define all(obj) (obj).begin(), (obj).end()
#define YESNO(bool) if(bool){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}
#define yesno(bool) if(bool){cout<<"yes"<<endl;}else{cout<<"no"<<endl;}
#define YesNo(bool) if(bool){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}

/* REP macro */
#define reps(i, a, n) for (ll i = (a); i < (ll)(n); ++i)
#define rep(i, n) reps(i, 0, n)
#define rrep(i, n) reps(i, 1, n + 1)
#define repd(i,n) for(ll i=n-1;i>=0;i--)
#define rrepd(i,n) for(ll i=n;i>=1;i--)
#define repsd(i, a, n) for(ll i=n;i>=a;i--)
#define fore(i,a) for(auto &i:a)

/* 追加分 */
#define vsort(v) sort(v.begin(), v.end())
#define verase(v) v.erase(unique(v.begin(), v.end()), v.end())
#define vlb(v, x) lower_bound(v.begin(), v.end(), x) - v.begin()
#define argsort(v) sort(xy.begin(), xy.end(), [](const auto &p1, const auto &p2) { return atan2l(p1.second, p1.first) < atan2l(p2.second, p2.first);})

/* debug */
// 標準エラー出力を含む提出はrejectされる場合もあるので注意
#define debug(x) cerr << "\033[33m(line:" << __LINE__ << ") " << #x << ": " << x << "\033[m" << endl;

/* int128 */
#define __int128_t ll

/* func */
inline int in_int() { int x; cin >> x; return x; }
inline ll in_ll() { ll x; cin >> x; return x; }
inline string in_str() { string x; cin >> x; return x; }
// search_length: 走査するベクトル長の上限(先頭から何要素目までを検索対象とするか、1始まりで)
template <typename T> inline bool vector_finder(std::vector<T> vec, T element, unsigned int search_length) {
    auto itr = std::find(vec.begin(), vec.end(), element);
    size_t index = std::distance(vec.begin(), itr);
    if (index == vec.size() || index >= search_length) { return false; }
    else { return true; }
}
template <typename T> inline void print(const vector<T>& v, string s = " ")
{
    rep(i, v.size()) cout << v[i] << (i != (ll)v.size() - 1 ? s : "\n");
}
template <typename T, typename S> inline void print(const pair<T, S>& p)
{
    cout << p.first << " " << p.second << endl;
}
template <typename T> inline void print(const T& x) { cout << x << "\n"; }
inline void printd(double x) { cout << fixed << setprecision(15) << x << endl; }
template <typename T, typename S> inline void print(const vector<pair<T, S>>& v)
{
    for (auto&& p : v) print(p);
}
// 第一引数と第二引数を比較し、第一引数(a)をより大きい/小さい値に上書き
template <typename T> inline bool chmin(T& a, const T& b) { bool compare = a > b; if (a > b) a = b; return compare; }
template <typename T> inline bool chmax(T& a, const T& b) { bool compare = a < b; if (a < b) a = b; return compare; }
// gcd lcm
// C++17からは標準実装
// template <typename T> T gcd(T a, T b) {if (b == 0)return a; else return gcd(b, a % b);}
// template <typename T> inline T lcm(T a, T b) {return (a * b) / gcd(a, b);}
// clang-format on

// 提出の際はコメントアウトすること
// #define __builtin_ctzll _tzcnt_u64
int alt__builtin_clz(unsigned int x)
{
    int rank = 0;
    while (x) {
        rank++;
        x >>= 1;
    }
    return 32 - rank;
}


static inline int alt__builtin_ctz(unsigned int x)
{
    rep(i, 32) {
        if (x & 1) return i;
        x >>= 1;
    }

}

static inline int alt__builtin_ctzll(unsigned long long x)
{
    rep(i, 64) {
        if (x & 1) return i;
        x >>= 1;
    }

}


template< typename T = int >
struct Edge {
    int from, to;
    T cost;
    int idx;

    Edge() = default;

    Edge(int from, int to, T cost = 1, int idx = -1) : from(from), to(to), cost(cost), idx(idx) {}

    operator int() const { return to; }
};

template< typename T = int >
struct Graph {
    vector< vector< Edge< T > > > g;
    int es;

    Graph() = default;

    explicit Graph(int n) : g(n), es(0) {}

    size_t size() const {
        return g.size();
    }

    void add_directed_edge(int from, int to, T cost = 1) {
        g[from].emplace_back(from, to, cost, es++);
    }

    void add_edge(int from, int to, T cost = 1) {
        g[from].emplace_back(from, to, cost, es);
        g[to].emplace_back(to, from, cost, es++);
    }

    void read(int M, int padding = -1, bool weighted = false, bool directed = false) {
        for (int i = 0; i < M; i++) {
            int a, b;
            cin >> a >> b;
            a += padding;
            b += padding;
            T c = T(1);
            if (weighted) cin >> c;
            if (directed) add_directed_edge(a, b, c);
            else add_edge(a, b, c);
        }
    }

    inline vector< Edge< T > >& operator[](const int& k) {
        return g[k];
    }

    inline const vector< Edge< T > >& operator[](const int& k) const {
        return g[k];
    }
};

template< typename T = int >
using Edges = vector< Edge< T > >;


template< class T >
struct Matrix {
    vector< vector< T > > A;

    Matrix() {}

    Matrix(size_t n, size_t m) : A(n, vector< T >(m, 0)) {}

    Matrix(size_t n) : A(n, vector< T >(n, 0)) {};

    size_t height() const {
        return (A.size());
    }

    size_t width() const {
        return (A[0].size());
    }

    inline const vector< T >& operator[](int k) const {
        return (A.at(k));
    }

    inline vector< T >& operator[](int k) {
        return (A.at(k));
    }

    static Matrix I(size_t n) {
        Matrix mat(n);
        for (int i = 0; i < n; i++) mat[i][i] = 1;
        return (mat);
    }

    Matrix& operator+=(const Matrix& B) {
        size_t n = height(), m = width();
        assert(n == B.height() && m == B.width());
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                (*this)[i][j] += B[i][j];
        return (*this);
    }

    Matrix& operator-=(const Matrix& B) {
        size_t n = height(), m = width();
        assert(n == B.height() && m == B.width());
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                (*this)[i][j] -= B[i][j];
        return (*this);
    }

    Matrix& operator*=(const Matrix& B) {
        size_t n = height(), m = B.width(), p = width();
        assert(p == B.height());
        vector< vector< T > > C(n, vector< T >(m, 0));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                for (int k = 0; k < p; k++)
                    C[i][j] = (C[i][j] + (*this)[i][k] * B[k][j]);
        A.swap(C);
        return (*this);
    }

    Matrix& operator^=(long long k) {
        Matrix B = Matrix::I(height());
        while (k > 0) {
            if (k & 1) B *= *this;
            *this *= *this;
            k >>= 1LL;
        }
        A.swap(B.A);
        return (*this);
    }

    Matrix operator+(const Matrix& B) const {
        return (Matrix(*this) += B);
    }

    Matrix operator-(const Matrix& B) const {
        return (Matrix(*this) -= B);
    }

    Matrix operator*(const Matrix& B) const {
        return (Matrix(*this) *= B);
    }

    Matrix operator^(const long long k) const {
        return (Matrix(*this) ^= k);
    }

    friend ostream& operator<<(ostream& os, Matrix& p) {
        size_t n = p.height(), m = p.width();
        for (int i = 0; i < n; i++) {
            os << "[";
            for (int j = 0; j < m; j++) {
                os << p[i][j] << (j + 1 == m ? "]\n" : ",");
            }
        }
        return (os);
    }


    T determinant() {
        Matrix B(*this);
        assert(width() == height());
        T ret = 1;
        for (int i = 0; i < width(); i++) {
            int idx = -1;
            for (int j = i; j < width(); j++) {
                if (B[j][i] != 0) idx = j;
            }
            if (idx == -1) return (0);
            if (i != idx) {
                ret *= -1;
                swap(B[i], B[idx]);
            }
            ret *= B[i][i];
            T vv = B[i][i];
            for (int j = 0; j < width(); j++) {
                B[i][j] /= vv;
            }
            for (int j = i + 1; j < width(); j++) {
                T a = B[j][i];
                for (int k = 0; k < width(); k++) {
                    B[j][k] -= B[i][k] * a;
                }
            }
        }
        return (ret);
    }
};


template <uint32_t mod>
struct LazyMontgomeryModInt {
    using mint = LazyMontgomeryModInt;
    using i32 = int32_t;
    using u32 = uint32_t;
    using u64 = uint64_t;

    static constexpr u32 get_r() {
        u32 ret = mod;
        for (i32 i = 0; i < 4; ++i) ret *= 2 - mod * ret;
        return ret;
    }

    static constexpr u32 r = get_r();
    static constexpr u32 n2 = (u64(0) - u64(mod)) % mod;

    static_assert(r* mod == 1, "invalid, r * mod != 1");
    static_assert(mod < (1 << 30), "invalid, mod >= 2 ^ 30");
    static_assert((mod & 1) == 1, "invalid, mod % 2 == 0");

    u32 a;

    constexpr LazyMontgomeryModInt() : a(0) {}
    constexpr LazyMontgomeryModInt(const int64_t& b)
        : a(reduce(u64(b% mod + mod)* n2)) {};

    static constexpr u32 reduce(const u64& b) {
        return (b + u64(u32(b) * u32(u32(0) - r)) * mod) >> 32;
    }

    constexpr mint& operator+=(const mint& b) {
        if (i32(a += b.a - 2 * mod) < 0) a += 2 * mod;
        return *this;
    }

    constexpr mint& operator-=(const mint& b) {
        if (i32(a -= b.a) < 0) a += 2 * mod;
        return *this;
    }

    constexpr mint& operator*=(const mint& b) {
        a = reduce(u64(a) * b.a);
        return *this;
    }

    constexpr mint& operator/=(const mint& b) {
        *this *= b.inverse();
        return *this;
    }

    constexpr mint operator+(const mint& b) const { return mint(*this) += b; }
    constexpr mint operator-(const mint& b) const { return mint(*this) -= b; }
    constexpr mint operator*(const mint& b) const { return mint(*this) *= b; }
    constexpr mint operator/(const mint& b) const { return mint(*this) /= b; }
    constexpr bool operator==(const mint& b) const {
        return (a >= mod ? a - mod : a) == (b.a >= mod ? b.a - mod : b.a);
    }
    constexpr bool operator!=(const mint& b) const {
        return (a >= mod ? a - mod : a) != (b.a >= mod ? b.a - mod : b.a);
    }
    constexpr mint operator-() const { return mint() - mint(*this); }

    constexpr mint pow(u64 n) const {
        mint ret(1), mul(*this);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    constexpr mint inverse() const { return pow(mod - 2); }

    friend ostream& operator<<(ostream& os, const mint& b) {
        return os << b.get();
    }

    friend istream& operator>>(istream& is, mint& b) {
        int64_t t;
        is >> t;
        b = LazyMontgomeryModInt<mod>(t);
        return (is);
    }

    constexpr u32 get() const {
        u32 ret = reduce(a);
        return ret >= mod ? ret - mod : ret;
    }

    static constexpr u32 get_mod() { return mod; }
};

template <typename mint>
struct NTT {
    static constexpr uint32_t get_pr() {
        uint32_t _mod = mint::get_mod();
        using u64 = uint64_t;
        u64 ds[32] = {};
        int idx = 0;
        u64 m = _mod - 1;
        for (u64 i = 2; i * i <= m; ++i) {
            if (m % i == 0) {
                ds[idx++] = i;
                while (m % i == 0) m /= i;
            }
        }
        if (m != 1) ds[idx++] = m;

        uint32_t _pr = 2;
        while (1) {
            int flg = 1;
            for (int i = 0; i < idx; ++i) {
                u64 a = _pr, b = (_mod - 1) / ds[i], r = 1;
                while (b) {
                    if (b & 1) r = r * a % _mod;
                    a = a * a % _mod;
                    b >>= 1;
                }
                if (r == 1) {
                    flg = 0;
                    break;
                }
            }
            if (flg == 1) break;
            ++_pr;
        }
        return _pr;
    };

    static constexpr uint32_t mod = mint::get_mod();
    static constexpr uint32_t pr = get_pr();
    static constexpr int level = 23;
    mint dw[level], dy[level];

    void setwy(int k) {
        mint w[level], y[level];
        w[k - 1] = mint(pr).pow((mod - 1) / (1 << k));
        y[k - 1] = w[k - 1].inverse();
        for (int i = k - 2; i > 0; --i)
            w[i] = w[i + 1] * w[i + 1], y[i] = y[i + 1] * y[i + 1];
        dw[1] = w[1], dy[1] = y[1], dw[2] = w[2], dy[2] = y[2];
        for (int i = 3; i < k; ++i) {
            dw[i] = dw[i - 1] * y[i - 2] * w[i];
            dy[i] = dy[i - 1] * w[i - 2] * y[i];
        }
    }

    NTT() { setwy(level); }

    void fft4(vector<mint>& a, int k) {
        if ((int)a.size() <= 1) return;
        if (k == 1) {
            mint a1 = a[1];
            a[1] = a[0] - a[1];
            a[0] = a[0] + a1;
            return;
        }
        if (k & 1) {
            int v = 1 << (k - 1);
            for (int j = 0; j < v; ++j) {
                mint ajv = a[j + v];
                a[j + v] = a[j] - ajv;
                a[j] += ajv;
            }
        }
        int u = 1 << (2 + (k & 1));
        int v = 1 << (k - 2 - (k & 1));
        mint one = mint(1);
        mint imag = dw[1];
        while (v) {
            // jh = 0
            {
                int j0 = 0;
                int j1 = v;
                int j2 = j1 + v;
                int j3 = j2 + v;
                for (; j0 < v; ++j0, ++j1, ++j2, ++j3) {
                    mint t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
                    mint t0p2 = t0 + t2, t1p3 = t1 + t3;
                    mint t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
                    a[j0] = t0p2 + t1p3, a[j1] = t0p2 - t1p3;
                    a[j2] = t0m2 + t1m3, a[j3] = t0m2 - t1m3;
                }
            }
            // jh >= 1
            mint ww = one, xx = one * dw[2], wx = one;
            for (int jh = 4; jh < u;) {
                ww = xx * xx, wx = ww * xx;
                int j0 = jh * v;
                int je = j0 + v;
                int j2 = je + v;
                for (; j0 < je; ++j0, ++j2) {
                    mint t0 = a[j0], t1 = a[j0 + v] * xx, t2 = a[j2] * ww,
                        t3 = a[j2 + v] * wx;
                    mint t0p2 = t0 + t2, t1p3 = t1 + t3;
                    mint t0m2 = t0 - t2, t1m3 = (t1 - t3) * imag;
                    a[j0] = t0p2 + t1p3, a[j0 + v] = t0p2 - t1p3;
                    a[j2] = t0m2 + t1m3, a[j2 + v] = t0m2 - t1m3;
                }
                xx *= dw[alt__builtin_ctzll((jh += 4))];
            }
            u <<= 2;
            v >>= 2;
        }
    }

    void ifft4(vector<mint>& a, int k) {
        if ((int)a.size() <= 1) return;
        if (k == 1) {
            mint a1 = a[1];
            a[1] = a[0] - a[1];
            a[0] = a[0] + a1;
            return;
        }
        int u = 1 << (k - 2);
        int v = 1;
        mint one = mint(1);
        mint imag = dy[1];
        while (u) {
            // jh = 0
            {
                int j0 = 0;
                int j1 = v;
                int j2 = v + v;
                int j3 = j2 + v;
                for (; j0 < v; ++j0, ++j1, ++j2, ++j3) {
                    mint t0 = a[j0], t1 = a[j1], t2 = a[j2], t3 = a[j3];
                    mint t0p1 = t0 + t1, t2p3 = t2 + t3;
                    mint t0m1 = t0 - t1, t2m3 = (t2 - t3) * imag;
                    a[j0] = t0p1 + t2p3, a[j2] = t0p1 - t2p3;
                    a[j1] = t0m1 + t2m3, a[j3] = t0m1 - t2m3;
                }
            }
            // jh >= 1
            mint ww = one, xx = one * dy[2], yy = one;
            u <<= 2;
            for (int jh = 4; jh < u;) {
                ww = xx * xx, yy = xx * imag;
                int j0 = jh * v;
                int je = j0 + v;
                int j2 = je + v;
                for (; j0 < je; ++j0, ++j2) {
                    mint t0 = a[j0], t1 = a[j0 + v], t2 = a[j2], t3 = a[j2 + v];
                    mint t0p1 = t0 + t1, t2p3 = t2 + t3;
                    mint t0m1 = (t0 - t1) * xx, t2m3 = (t2 - t3) * yy;
                    a[j0] = t0p1 + t2p3, a[j2] = (t0p1 - t2p3) * ww;
                    a[j0 + v] = t0m1 + t2m3, a[j2 + v] = (t0m1 - t2m3) * ww;
                }
                xx *= dy[alt__builtin_ctzll(jh += 4)];
            }
            u >>= 4;
            v <<= 2;
        }
        if (k & 1) {
            u = 1 << (k - 1);
            for (int j = 0; j < u; ++j) {
                mint ajv = a[j] - a[j + u];
                a[j] += a[j + u];
                a[j + u] = ajv;
            }
        }
    }

    void ntt(vector<mint>& a) {
        if ((int)a.size() <= 1) return;
        fft4(a, alt__builtin_ctz(a.size()));
    }

    void intt(vector<mint>& a) {
        if ((int)a.size() <= 1) return;
        ifft4(a, alt__builtin_ctz(a.size()));
        mint iv = mint(a.size()).inverse();
        for (auto& x : a) x *= iv;
    }

    vector<mint> multiply(const vector<mint>& a, const vector<mint>& b) {
        int l = a.size() + b.size() - 1;
        if (min<int>(a.size(), b.size()) <= 40) {
            vector<mint> s(l);
            for (int i = 0; i < (int)a.size(); ++i)
                for (int j = 0; j < (int)b.size(); ++j) s[i + j] += a[i] * b[j];
            return s;
        }
        int k = 2, M = 4;
        while (M < l) M <<= 1, ++k;
        setwy(k);
        vector<mint> s(M), t(M);
        for (int i = 0; i < (int)a.size(); ++i) s[i] = a[i];
        for (int i = 0; i < (int)b.size(); ++i) t[i] = b[i];
        fft4(s, k);
        fft4(t, k);
        for (int i = 0; i < M; ++i) s[i] *= t[i];
        ifft4(s, k);
        s.resize(l);
        mint invm = mint(M).inverse();
        for (int i = 0; i < l; ++i) s[i] *= invm;
        return s;
    }

    void ntt_doubling(vector<mint>& a) {
        int M = (int)a.size();
        auto b = a;
        intt(b);
        mint r = 1, zeta = mint(pr).pow((mint::get_mod() - 1) / (M << 1));
        for (int i = 0; i < M; i++) b[i] *= r, r *= zeta;
        ntt(b);
        copy(begin(b), end(b), back_inserter(a));
    }
};

template <typename mint>
struct FormalPowerSeries : vector<mint> {
    using vector<mint>::vector;
    using FPS = FormalPowerSeries;

    FPS& operator+=(const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); i++) (*this)[i] += r[i];
        return *this;
    }

    FPS& operator+=(const mint& r) {
        if (this->empty()) this->resize(1);
        (*this)[0] += r;
        return *this;
    }

    FPS& operator-=(const FPS& r) {
        if (r.size() > this->size()) this->resize(r.size());
        for (int i = 0; i < (int)r.size(); i++) (*this)[i] -= r[i];
        return *this;
    }

    FPS& operator-=(const mint& r) {
        if (this->empty()) this->resize(1);
        (*this)[0] -= r;
        return *this;
    }

    FPS& operator*=(const mint& v) {
        for (int k = 0; k < (int)this->size(); k++) (*this)[k] *= v;
        return *this;
    }

    FPS& operator/=(const FPS& r) {
        if (this->size() < r.size()) {
            this->clear();
            return *this;
        }
        int n = this->size() - r.size() + 1;
        if ((int)r.size() <= 64) {
            FPS f(*this), g(r);
            g.shrink();
            mint coeff = g.back().inverse();
            for (auto& x : g) x *= coeff;
            int deg = (int)f.size() - (int)g.size() + 1;
            int gs = g.size();
            FPS quo(deg);
            for (int i = deg - 1; i >= 0; i--) {
                quo[i] = f[i + gs - 1];
                for (int j = 0; j < gs; j++) f[i + j] -= quo[i] * g[j];
            }
            *this = quo * coeff;
            this->resize(n, mint(0));
            return *this;
        }
        return *this = ((*this).rev().pre(n) * r.rev().inv(n)).pre(n).rev();
    }

    FPS& operator%=(const FPS& r) {
        *this -= *this / r * r;
        shrink();
        return *this;
    }

    FPS operator+(const FPS& r) const { return FPS(*this) += r; }
    FPS operator+(const mint& v) const { return FPS(*this) += v; }
    FPS operator-(const FPS& r) const { return FPS(*this) -= r; }
    FPS operator-(const mint& v) const { return FPS(*this) -= v; }
    FPS operator*(const FPS& r) const { return FPS(*this) *= r; }
    FPS operator*(const mint& v) const { return FPS(*this) *= v; }
    FPS operator/(const FPS& r) const { return FPS(*this) /= r; }
    FPS operator%(const FPS& r) const { return FPS(*this) %= r; }
    FPS operator-() const {
        FPS ret(this->size());
        for (int i = 0; i < (int)this->size(); i++) ret[i] = -(*this)[i];
        return ret;
    }

    void shrink() {
        while (this->size() && this->back() == mint(0)) this->pop_back();
    }

    FPS rev() const {
        FPS ret(*this);
        reverse(begin(ret), end(ret));
        return ret;
    }

    FPS dot(FPS r) const {
        FPS ret(min(this->size(), r.size()));
        for (int i = 0; i < (int)ret.size(); i++) ret[i] = (*this)[i] * r[i];
        return ret;
    }

    FPS pre(int sz) const {
        return FPS(begin(*this), begin(*this) + min((int)this->size(), sz));
    }

    FPS operator>>(int sz) const {
        if ((int)this->size() <= sz) return {};
        FPS ret(*this);
        ret.erase(ret.begin(), ret.begin() + sz);
        return ret;
    }

    FPS operator<<(int sz) const {
        FPS ret(*this);
        ret.insert(ret.begin(), sz, mint(0));
        return ret;
    }

    FPS diff() const {
        const int n = (int)this->size();
        FPS ret(max(0, n - 1));
        mint one(1), coeff(1);
        for (int i = 1; i < n; i++) {
            ret[i - 1] = (*this)[i] * coeff;
            coeff += one;
        }
        return ret;
    }

    FPS integral() const {
        const int n = (int)this->size();
        FPS ret(n + 1);
        ret[0] = mint(0);
        if (n > 0) ret[1] = mint(1);
        auto mod = mint::get_mod();
        for (int i = 2; i <= n; i++) ret[i] = (-ret[mod % i]) * (mod / i);
        for (int i = 0; i < n; i++) ret[i + 1] *= (*this)[i];
        return ret;
    }

    mint eval(mint x) const {
        mint r = 0, w = 1;
        for (auto& v : *this) r += w * v, w *= x;
        return r;
    }

    FPS log(int deg = -1) const {
        assert((*this)[0] == mint(1));
        if (deg == -1) deg = (int)this->size();
        return (this->diff() * this->inv(deg)).pre(deg - 1).integral();
    }

    FPS pow(int64_t k, int deg = -1) const {
        const int n = (int)this->size();
        if (deg == -1) deg = n;
        if (k == 0) {
            FPS ret(deg);
            if (deg) ret[0] = 1;
            return ret;
        }
        for (int i = 0; i < n; i++) {
            if ((*this)[i] != mint(0)) {
                mint rev = mint(1) / (*this)[i];
                FPS ret = (((*this * rev) >> i).log(deg) * k).exp(deg);
                ret *= (*this)[i].pow(k);
                ret = (ret << (i * k)).pre(deg);
                if ((int)ret.size() < deg) ret.resize(deg, mint(0));
                return ret;
            }
            if (__int128_t(i + 1) * k >= deg) return FPS(deg, mint(0));
        }
        return FPS(deg, mint(0));
    }

    static void* ntt_ptr;
    static void set_fft();
    FPS& operator*=(const FPS& r);
    void ntt();
    void intt();
    void ntt_doubling();
    static int ntt_pr();
    FPS inv(int deg = -1) const;
    FPS exp(int deg = -1) const;
};
template <typename mint>
void* FormalPowerSeries<mint>::ntt_ptr = nullptr;

template <typename mint>
void FormalPowerSeries<mint>::set_fft() {
    if (!ntt_ptr) ntt_ptr = new NTT<mint>;
}

template <typename mint>
FormalPowerSeries<mint>& FormalPowerSeries<mint>::operator*=(
    const FormalPowerSeries<mint>& r) {
    if (this->empty() || r.empty()) {
        this->clear();
        return *this;
    }
    set_fft();
    auto ret = static_cast<NTT<mint>*>(ntt_ptr)->multiply(*this, r);
    return *this = FormalPowerSeries<mint>(ret.begin(), ret.end());
}

template <typename mint>
void FormalPowerSeries<mint>::ntt() {
    set_fft();
    static_cast<NTT<mint>*>(ntt_ptr)->ntt(*this);
}

template <typename mint>
void FormalPowerSeries<mint>::intt() {
    set_fft();
    static_cast<NTT<mint>*>(ntt_ptr)->intt(*this);
}

template <typename mint>
void FormalPowerSeries<mint>::ntt_doubling() {
    set_fft();
    static_cast<NTT<mint>*>(ntt_ptr)->ntt_doubling(*this);
}

template <typename mint>
int FormalPowerSeries<mint>::ntt_pr() {
    set_fft();
    return static_cast<NTT<mint>*>(ntt_ptr)->pr;
}

template <typename mint>
FormalPowerSeries<mint> FormalPowerSeries<mint>::inv(int deg) const {
    assert((*this)[0] != mint(0));
    if (deg == -1) deg = (int)this->size();
    FormalPowerSeries<mint> res(deg);
    res[0] = { mint(1) / (*this)[0] };
    for (int d = 1; d < deg; d <<= 1) {
        FormalPowerSeries<mint> f(2 * d), g(2 * d);
        for (int j = 0; j < min((int)this->size(), 2 * d); j++) f[j] = (*this)[j];
        for (int j = 0; j < d; j++) g[j] = res[j];
        f.ntt();
        g.ntt();
        for (int j = 0; j < 2 * d; j++) f[j] *= g[j];
        f.intt();
        for (int j = 0; j < d; j++) f[j] = 0;
        f.ntt();
        for (int j = 0; j < 2 * d; j++) f[j] *= g[j];
        f.intt();
        for (int j = d; j < min(2 * d, deg); j++) res[j] = -f[j];
    }
    return res.pre(deg);
}

template <typename mint>
FormalPowerSeries<mint> FormalPowerSeries<mint>::exp(int deg) const {
    using fps = FormalPowerSeries<mint>;
    assert((*this).size() == 0 || (*this)[0] == mint(0));
    if (deg == -1) deg = this->size();

    fps inv;
    inv.reserve(deg + 1);
    inv.push_back(mint(0));
    inv.push_back(mint(1));

    auto inplace_integral = [&](fps& F) -> void {
        const int n = (int)F.size();
        auto mod = mint::get_mod();
        while ((int)inv.size() <= n) {
            int i = inv.size();
            inv.push_back((-inv[mod % i]) * (mod / i));
        }
        F.insert(begin(F), mint(0));
        for (int i = 1; i <= n; i++) F[i] *= inv[i];
    };

    auto inplace_diff = [](fps& F) -> void {
        if (F.empty()) return;
        F.erase(begin(F));
        mint coeff = 1, one = 1;
        for (int i = 0; i < (int)F.size(); i++) {
            F[i] *= coeff;
            coeff += one;
        }
    };

    fps b{ 1, 1 < (int)this->size() ? (*this)[1] : 0 }, c{ 1 }, z1, z2{ 1, 1 };
    for (int m = 2; m < deg; m *= 2) {
        auto y = b;
        y.resize(2 * m);
        y.ntt();
        z1 = z2;
        fps z(m);
        for (int i = 0; i < m; ++i) z[i] = y[i] * z1[i];
        z.intt();
        fill(begin(z), begin(z) + m / 2, mint(0));
        z.ntt();
        for (int i = 0; i < m; ++i) z[i] *= -z1[i];
        z.intt();
        c.insert(end(c), begin(z) + m / 2, end(z));
        z2 = c;
        z2.resize(2 * m);
        z2.ntt();
        fps x(begin(*this), begin(*this) + min<int>(this->size(), m));
        x.resize(m);
        inplace_diff(x);
        x.push_back(mint(0));
        x.ntt();
        for (int i = 0; i < m; ++i) x[i] *= y[i];
        x.intt();
        x -= b.diff();
        x.resize(2 * m);
        for (int i = 0; i < m - 1; ++i) x[m + i] = x[i], x[i] = mint(0);
        x.ntt();
        for (int i = 0; i < 2 * m; ++i) x[i] *= z2[i];
        x.intt();
        x.pop_back();
        inplace_integral(x);
        for (int i = m; i < min<int>(this->size(), 2 * m); ++i) x[i] += (*this)[i];
        fill(begin(x), begin(x) + m, mint(0));
        x.ntt();
        for (int i = 0; i < 2 * m; ++i) x[i] *= y[i];
        x.intt();
        b.insert(end(b), begin(x) + m, end(x));
    }
    return fps{ begin(b), begin(b) + deg };
}


template <typename T> inline void print(const FormalPowerSeries<T>& v, string s = " ")
{
    rep(i, v.size()) cout << v[i] << (i != (ll)v.size() - 1 ? s : "\n");
}

using mint = LazyMontgomeryModInt<998244353>;
using fps = FormalPowerSeries<mint>;



// 定数
const ll INF = 1ll << 60;
const vi dd({ -1,0,1,0,-1 });
const double PI = atan(1) * 4;
double eps = 1e-10;
const ll MOD = 998244353;

// 最大公約数
ll gcd(ll a, ll b) {
    if (!b) return a;
    if (a % b == 0) return b;
    else return gcd(b, a % b);
}

// 最小公倍数
ll lcm(ll a, ll b) {
    return a * b / gcd(a, b);
}

// インタラクティブ用
void question(vll v) {
    cout << "?";
    rep(i, v.size()) {
        cout << " " << v[i];
    }
    cout << endl;
}
void answer(vll v) {
    cout << "!";
    rep(i, v.size()) {
        cout << " " << v[i];
    }
    cout << endl;
}

// 等差数列
ll arith_sum1(ll left, ll right, ll d) {
    return (left + right) * (right - left + d) / (2 * d);
}
ll arith_sum2(ll left, ll d, ll num) {
    return arith_sum1(left, left + d * (num - 1), d);
}

// 座標圧縮
void comp(vll& a) {
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
}


// 区間min(+idx)遅延セグ木テンプレート
struct S {
    ll val, idx;
};
struct F {
    ll x;
};
S min_op(S l, S r) {
    if (l.val < r.val) return l;
    else return r;
}
S min_e() { return { INF, -1 }; }
S max_op(S l, S r) {
    if (l.val > r.val) return l;
    else return r;
}
S max_e() { return { -INF, -1 }; }
S mapping(F l, S r) { return { l.x + r.val, r.idx }; }
F composition(F l, F r) { return { l.x + r.x }; }
F id() { return { 0 }; }

S plus_op(S l, S r) {
    S ans{ l.val + r.val, 0ll };
    return ans;
}
S plus_e() { return { 0, -1 }; }

//lazy_segtree<S, min_op, min_e, F, mapping, composition, id> seg(n);
/**
 * @brief Fibonacchi-Heap(フィボナッチヒープ)
 * @see https://www.cs.princeton.edu/~wayne/teaching/fibonacci-heap.pdf
 */
template< typename key_t, typename val_t >
struct FibonacchiHeap {
    struct Node {
        key_t key;
        val_t val;
        Node* left, * right, * child, * par;
        int sz;
        bool mark;

        Node(const key_t& key, const val_t& val)
            : key(key), val(val), left(this), right(this), par(nullptr), child(nullptr), sz(0), mark(false) {}
    };

    Node* root;
    size_t sz;
    vector< Node* > rank;

    FibonacchiHeap() : root(nullptr), sz(0) {}

    size_t size() const {
        return sz;
    }

    bool empty() const {
        return sz == 0;
    }

    void update_min(Node* t) {
        if (!root || t->key < root->key) {
            root = t;
        }
    }

    void concat(Node*& r, Node* t) {
        if (!r) {
            r = t;
        }
        else {
            t->left->right = r->right;
            r->right->left = t->left;
            t->left = r;
            r->right = t;
        }
    }

    void delete_node(Node* t) {
        t->left->right = t->right;
        t->right->left = t->left;
        t->left = t;
        t->right = t;
    }

    Node* push(const key_t& key, const val_t& val) {
        ++sz;
        auto node = new Node(key, val);
        concat(root, node);
        update_min(node);
        return node;
    }


    Node* consolidate(Node* s, Node* t) {
        if (root == s || s->key < t->key) {
            delete_node(t);
            ++s->sz;
            t->par = s;
            concat(s->child, t);
            return s;
        }
        else {
            delete_node(s);
            ++t->sz;
            s->par = t;
            concat(t->child, s);
            return t;
        }
    }


    pair< key_t, val_t > pop() {
        --sz;

        Node* rem = root;


        auto ret = make_pair(rem->key, rem->val);

        {
            root = root->left == root ? nullptr : root->left;
            delete_node(rem);
        }


        if (rem->child) {
            concat(root, rem->child);
        }


        if (root) {

            {
                Node* base = root, * cur = base;
                do {
                    cur->par = nullptr;
                    update_min(cur);
                    cur = cur->right;
                } while (cur != base);
            }


            {
                Node* base = root;
                int last = -1;
                do {
                    Node* nxt = base->right;
                    while (base->sz < rank.size() && rank[base->sz]) {
                        Node* u = rank[base->sz];
                        rank[base->sz] = nullptr;
                        base = consolidate(u, base);
                    }
                    if (base->sz >= rank.size()) rank.resize(base->sz + 1);
                    last = max(last, base->sz);
                    rank[base->sz] = base;
                    base = nxt;
                } while (base != root);

                for (int i = last; i >= 0; i--) rank[i] = nullptr;
            }
        }

        return ret;
    }

    inline void mark_dfs(Node* t) {
        if (!t->par) {
            t->mark = false;
        }
        else if (t->mark) {
            mark_dfs(t->par);
            t->par->child = t->left == t ? nullptr : t->left;
            delete_node(t);
            t->sz--;
            t->mark = false;
            t->par = nullptr;
            concat(root, t);
        }
        else {
            t->mark = true;
            t->sz--;
        }
    }


    void decrease_key(Node* t, const key_t& d) {
        t->key -= d;

        if (!t->par) {
            update_min(t);
            return;
        }

        if (t->par->key <= t->key) {
            return;
        }

        t->sz++;
        t->mark = true;
        mark_dfs(t);
        update_min(t);
    }
};

template< typename T >
vector< T > dijkstra_fibonacchi_heap(Graph< T >& g, int s) {
    const auto INF = numeric_limits< T >::max();
    using Heap = FibonacchiHeap< T, int >;
    using Node = typename Heap::Node;

    Heap heap;
    vector< Node* > keep(g.size(), nullptr);
    vector< T > dist;
    dist.assign(g.size(), INF);
    dist[s] = 0;
    keep[s] = heap.push(dist[s], s);

    while (!heap.empty()) {
        T cost;
        int idx;
        tie(cost, idx) = heap.pop();
        if (dist[idx] < cost) continue;
        for (auto& e : g[idx]) {
            auto next_cost = cost + e.cost;
            if (dist[e.to] <= next_cost) continue;
            if (keep[e.to] == nullptr) {
                dist[e.to] = next_cost;
                keep[e.to] = heap.push(dist[e.to], e.to);
            }
            else {
                T d = dist[e.to] - next_cost;
                heap.decrease_key(keep[e.to], d);
                dist[e.to] -= d;
            }
        }
    }
    return dist;
}

int main() {

    ll n, m;
    cin >> n >> m;
    vll a(n), b(n), c(n);
    rep(i, n) cin >> a[i];
    rep(i, m) cin >> b[i];
    rep(i, n) cin >> c[i];


    ll sum = 0;
    rep(i, n) sum += c[i];

    map<ll, ll> mp;
    ll val = 0;
    rep(i, n) {
        mp[val - a[i]] -= c[i];
        val += b[i % m];
    }

    ll cost = 0;
    fore(e, mp) {
        chmin(cost, e.second);
    }
    cost += sum;
    print(cost);

}
0