답안 #865698

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
865698 2023-10-24T14:15:24 Z azimanov 수열 (BOI14_sequence) C++17
67 / 100
954 ms 82624 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

template<int mod>
class Modular {
public:
    int val;
    Modular() : val(0) {}
    Modular(int new_val) : val(new_val) {
    }
    friend Modular operator+(const Modular& a, const Modular& b) {
        if (a.val + b.val >= mod) return a.val + b.val - mod;
        else return a.val + b.val;
    }
    friend Modular operator-(const Modular& a, const Modular& b) {
        if (a.val - b.val < 0) return a.val - b.val + mod;
        else return a.val - b.val;
    }
    friend Modular operator*(const Modular& a, const Modular& b) {
        return 1ll * a.val * b.val % mod;
    }
    friend Modular binpow(Modular a, long long n) {
        Modular res = 1;
        for (; n; n >>= 1) {
            if (n & 1) res *= a;
            a *= a;
        }
        return res;
    }
    /* ALTERNATIVE INVERSE FUNCTION USING EXTENDED EUCLIDEAN ALGORITHM
    friend void gcd(int a, int b, Modular& x, Modular& y) {
        if (a == 0) {
            x = Modular(0);
            y = Modular(1);
            return;
        }
        Modular x1, y1;
        gcd(b % a, a, x1, y1);
        x = y1 - (b / a) * x1;
        y = x1;
    }
    friend Modular inv(const Modular& a) {
        Modular x, y;
        gcd(a.val, mod, x, y);
        return x;
    }
    */
    friend Modular inv(const Modular& a) {
        return binpow(a, mod - 2);
    }
    Modular operator/(const Modular& ot) const {
        return *this * inv(ot);
    }
    Modular& operator++() {
        if (val + 1 == mod) val = 0;
        else ++val;
        return *this;
    }
    Modular operator++(int) {
        Modular tmp = *this;
        ++(*this);
        return tmp;
    }
    Modular operator+() const {
        return *this;
    }
    Modular operator-() const {
        return 0 - *this;
    }
    Modular& operator+=(const Modular& ot) {
        return *this = *this + ot;
    }
    Modular& operator-=(const Modular& ot) {
        return *this = *this - ot;
    }
    Modular& operator*=(const Modular& ot) {
        return *this = *this * ot;
    }
    Modular& operator/=(const Modular& ot) {
        return *this = *this / ot;
    }
    bool operator==(const Modular& ot) const {
        return val == ot.val;
    }
    bool operator!=(const Modular& ot) const {
        return val != ot.val;
    }
    bool operator<(const Modular& ot) const {
        return val < ot.val;
    }
    bool operator>(const Modular& ot) const {
        return val > ot.val;
    }
    explicit operator int() const {
        return val;
    }
};

template <int mod>
Modular<mod> any_to_mint(ll a) {
    a %= mod;
    return a < 0 ? a + mod : a;
}

template<int mod>
istream& operator>>(istream& istr, Modular<mod>& x) {
    return istr >> x.val;
}

template<int mod>
ostream& operator<<(ostream& ostr, const Modular<mod>& x) {
    return ostr << x.val;
}

template <int mod = 998244353, int root = 3>
class NTT {
    using Mint = Modular<mod>;
public:
    static vector<int> mult(const vector<int>& a, const vector<int>& b) {
        vector<Mint> amod(a.size());
        vector<Mint> bmod(b.size());
        for (int i = 0; i < a.size(); i++) {
            amod[i] = any_to_mint<mod>(a[i]);
        }
        for (int i = 0; i < b.size(); i++) {
            bmod[i] = any_to_mint<mod>(b[i]);
        }
        vector<Mint> resmod = mult(amod, bmod);
        vector<int> res(resmod.size());
        for (int i = 0; i < res.size(); i++) {
            res[i] = resmod[i].val;
        }
        return res;
    }
    static vector<Mint> mult(const vector<Mint>& a, const vector<Mint>& b) {
        int n = int(a.size()), m = int(b.size());
        if (!n || !m) return {};
        int lg = 0;
        while ((1 << lg) < n + m - 1) lg++;
        int z = 1 << lg;
        auto a2 = a, b2 = b;
        a2.resize(z);
        b2.resize(z);
        nft(false, a2);
        nft(false, b2);
        for (int i = 0; i < z; i++) a2[i] *= b2[i];
        nft(true, a2);
        a2.resize(n + m - 1);
        Mint iz = inv(Mint(z));
        for (int i = 0; i < n + m - 1; i++) a2[i] *= iz;
        return a2;
    }

private:
    static void nft(bool type, vector<Modular<mod>> &a) {
        int n = int(a.size()), s = 0;
        while ((1 << s) < n) s++;
        assert(1 << s == n);
        static vector<Mint> ep, iep;
        while (int(ep.size()) <= s) {
            ep.push_back(binpow(Mint(root), (mod - 1) / (1 << ep.size())));
            iep.push_back(inv(ep.back()));
        }
        vector<Mint> b(n);
        for (int i = 1; i <= s; i++) {
            int w = 1 << (s - i);
            Mint base = type ? iep[i] : ep[i], now = 1;
            for (int y = 0; y < n / 2; y += w) {
                for (int x = 0; x < w; x++) {
                    auto l = a[y << 1 | x];
                    auto r = now * a[y << 1 | x | w];
                    b[y | x] = l + r;
                    b[y | x | n >> 1] = l - r;
                }
                now *= base;
            }
            swap(a, b);
        }
    }
};

const ll inf = 1e18;
const int L = 18;
const int C = 10;
const int N = 1e5 + 10;
const int M = 1e6 + 1e5 + 10;

int cnt_suf[C][M];

ll pw10[L];
int flag[N];
ll dp[(1 << C)][(1 << C)];

int flag_true[N + N];
int rig_true[C][N + N];

int b[N];
int lef[C][N], rig[C][N];
int pref[C][N], suf[C][N];

bool getbit(int mask, int bit) {
    return mask & (1 << bit);
}

ll mask_to_ll(int mask) {
    ll res = 0;
    for (int i = 1; i < C; i++) {
        if (getbit(mask, i)) {
            res = res * 10 + i;
            mask ^= (1 << i);
            break;
        }
    }
    for (int i = 0; i < C; i++) {
        if (getbit(mask, i)) {
            res = res * 10 + i;
        }
    }
    return res;
}

int vec_to_mask(const vector<int>& vec) {
    int mask = 0;
    for (int i : vec) {
        mask |= (1 << i);
    }
    return mask;
}

void init() {
    {
        for (int x = M - 1; x >= 1; x /= 10) {
            cnt_suf[x % 10][M - 1]++;
        }
    }
    for (int i = M - 2; i >= 1; i--) {
        int mask = 0;
        for (int x = i; x >= 1; x /= 10) {
            mask |= (1 << (x % 10));
        }
        for (int c = 0; c < C; c++) {
            if (getbit(mask, c)) {
                cnt_suf[c][i] = cnt_suf[c][i + 1] + 1;
            } else {
                cnt_suf[c][i] = 0;
            }
        }
    }

    pw10[0] = 1;
    for (int i = 1; i < L; i++) {
        pw10[i] = pw10[i - 1] * 10;
    }

    flag[0] = (1 << 0);
    for (int i = 1; i <= N - 1; i++) {
        for (int j = i; j >= 1; j /= 10) {
            flag[i] |= (1 << (j % 10));
        }
        if (i <= 9'999) {
            flag[i] |= (1 << 0); ///////////////////////////////////////////////////////////////////////////////////////
        }
    }

    flag_true[0] = (1 << 0);
    for (int i = 1; i <= 2 * N - 1; i++) {
        for (int j = i; j >= 1; j /= 10) {
            flag_true[i] |= (1 << (j % 10));
        }
    }

    for (int i = 0; i < (1 << C); i++) {
        for (int j = 0; j < (1 << C); j++) {
            dp[i][j] = inf;
        }
    }
    for (int mask = 0; mask < (1 << C); mask++) {
        for (int last = 0; last < C && last != 9; last++) {
            int pref_mask = mask | (1 << last);
            int suf_mask = mask | (1 << (last + 1));
            if (mask_to_ll(mask) != 0 || last != 0) {
                dp[pref_mask][suf_mask] = min(dp[pref_mask][suf_mask], mask_to_ll(mask == 1 ? 3 : mask) * 10 + last);
            }

            pref_mask = mask | (mask == 0 && last == 0 ? 0 : (1 << last)) | (1 << 9);
            suf_mask = mask | (1 << (last + 1)) | (1 << 0);
            dp[pref_mask][suf_mask] = min(dp[pref_mask][suf_mask], mask_to_ll(mask == 1 ? 3 : mask) * 100 + last * 10 + 9);
        }
    }
    for (int i = (1 << C) - 1; i >= 0; i--) {
        for (int j = (1 << C) - 1; j >= 0; j--) {
            for (int c = 0; c < C; c++) {
                dp[i][j] = min(dp[i][j], dp[i | (1 << c)][j]);
                dp[i][j] = min(dp[i][j], dp[i][j | (1 << c)]);
            }
        }
    }
}

void calc_lef_rig(int k) {
    const int n = 100'000;
    for (int c = 0; c < C; c++) {
        vector<int> p(n, 0);
        vector<int> q(k, 0);
        for (int i = 0; i < n; i++) {
            p[i] = getbit(flag[i], c);
        }
        for (int i = 1; i <= k; i++) {
            q[k - i] = b[i] == c;
        }
        auto r = NTT<998244353, 3>::mult(p, q);
        for (int i = 0; i < n; i++) {
            lef[c][i] = r[i];
            rig[c][i] = r[i + k - 1];
        }
    }
}

void calc_pref_suf(int k) {
    for (int c = 0; c < C; c++) {
        pref[c][0] = 0;
        suf[c][k + 1] = 0;
    }
    for (int i = 1; i <= k; i++) {
        for (int c = 0; c < C; c++) {
            pref[c][i] = pref[c][i - 1];
        }
        pref[b[i]][i]++;
    }
    for (int i = k; i >= 1; i--) {
        for (int c = 0; c < C; c++) {
            suf[c][i] = suf[c][i + 1];
        }
        suf[b[i]][i]++;
    }
}

void calc_rig_true(int k) {
    const int n = 200'000;
    for (int c = 0; c < C; c++) {
        vector<int> p(n, 0);
        vector<int> q(k, 0);
        for (int i = 0; i < n; i++) {
            p[i] = getbit(flag_true[i], c);
        }
        for (int i = 1; i <= k; i++) {
            q[k - i] = b[i] == c;
        }
        auto r = NTT<998244353, 3>::mult(p, q);
        for (int i = 0; i < n; i++) {
            rig_true[c][i] = r[i + k - 1];
        }
    }
}

ll solve_small(int k) {
    const int n = 100'000;
    for (int i = 1; i < n; i++) {
        bool ok = true;
        for (int c = 0; c < C; c++) {
            ok &= rig_true[c][i] == pref[c][k];
        }
        if (ok) {
            return i;
        }
    }
    return inf;
}

ll solve(int k) {
    calc_lef_rig(k);
    calc_rig_true(k);
    calc_pref_suf(k);

    const int n = 100'000;
    ll ans = inf;

    ans = min(ans, solve_small(k));

    for (int i = 0; i < n; i++) {
        if (i + k - 1 < n) {
            int need = 0;
            for (int c = 0; c < C; c++) {
                if (rig[c][i] != pref[c][k]) {
                    need |= (1 << c);
                }
            }
            ans = min(ans, dp[need][0] * n + i);
        } else {
            int len_pref = n - i;
            int len_suf = k - len_pref;
            int need_pref = 0, need_suf = 0;
            for (int c = 0; c < C; c++) {
                if (rig[c][i] != pref[c][len_pref]) {
                    need_pref |= (1 << c);
                }
                if (lef[c][len_suf - 1] != suf[c][len_suf]) {
                    need_suf |= (1 << c);
                }
            }
            ans = min(ans, dp[need_pref][need_suf] * n + i);
        }
    }
    return ans;
}

ll solve_same(int k) {
    for (int i = 1; i <= k - 1; i++) {
        if (b[i] != b[i + 1]) {
            return inf;
        }
    }
    for (int n = 1; n + k - 1 <= M - 1; n++) {
        if (cnt_suf[b[1]][n] >= k) {
            return n;
        }
    }
    return -1;
}

ll slow(int k) {
    for (int n = 1; n <= 1000; n++) {
        bool ok = true;
        for (int i = 1; i <= k; i++) {
            ok &= getbit(flag_true[n + i - 1], b[i]);
        }
        if (ok) {
            return n;
        }
    }
    return -1;
}

void stress() {
    mt19937 rnd;
    while (true) {
        int k = rnd() % 100 + 1;
        for (int i = 1; i <= k; i++) {
            b[i] = rnd() % C;
        }
        ll res = slow(k);
        if (res == -1) {
            continue;
        }
        ll ans = solve(k);
        if (ans == res) {
            cout << "OK" << endl;
        } else {
            cout << "WA\n";
            cout << k << "\n";
            for (int i = 1; i <= k; i++) {
                cout << b[i] << " ";
            }
            cout << "\n\n";
            cout << ans << " " << res << "\n";
            break;
        }
    }
    exit(0);
}

void gen_same(int& k, int trg_k, int trg_b) {
    k = trg_k;
    for (int i = 1; i <= k; i++) {
        b[i] = trg_b;
    }
}

void stress_same() {
    mt19937 rnd;
    while (true) {
        int k = rnd() % 1000 + 99000;
        b[1] = rnd() % C;
        for (int i = 2; i <= k; i++) {
            b[i] = b[i - 1];
        }

        ll ans = solve(k);
        ll res = solve_same(k);

        if (ans == res) {
            cout << "OK" << endl;
        } else {
            cout << "WA\n";
            cout << k << "\n";
            cout << "b[i] = " << b[1] << "\n";
            cout << "\n\n";
            cout << ans << " " << res << "\n";
            break;
        }
    }
    exit(0);
}

ll dp_slow[(1 << C)][(1 << C)];

int ll_to_mask(ll x) {
    int mask = 0;
    while (x > 0) {
        mask |= (1 << (x % 10));
        x /= 10;
    }
    return mask;
}

void stress_dp() {
    for (int i = 0; i < (1 << C); i++) {
        for (int j = 0; j < (1 << C); j++) {
            dp_slow[i][j] = inf;
        }
    }
    for (int i = 1; i <= 1e7; i++) {
        int x = ll_to_mask(i);
        int y = ll_to_mask(i + 1);
        dp_slow[x][y] = min(dp_slow[x][y], ll(i));
    }
    for (int i = 0; i < (1 << C); i++) {
        for (int j = 0; j < (1 << C); j++) {
            if (dp_slow[i][j] != inf && dp[i][j] != dp_slow[i][j]) {
                cout << "WA\n";
                cout << i << " " << j << "\n";
                cout << dp[i][j] << " " << dp_slow[i][j] << "\n";
                exit(0);
            }
        }
    }
    cout << "OK" << endl;
    exit(0);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif

    init();

    // stress();
    // stress_same();
    // stress_dp();

    // cout << dp[vec_to_mask({1, 2, 3})][vec_to_mask({9, 0, 1, 4})] << "\n";

    int k;
    cin >> k;
    for (int i = 1; i <= k; i++) {
        cin >> b[i];
    }

    // gen_same(k, 90239, 0);

    cout << solve(k) << "\n";
    // cout << solve_same(k) << "\n";

#ifdef LOCAL
    cout << "\nTime elapsed: " << double(clock()) / CLOCKS_PER_SEC << " s.\n";
#endif
}

Compilation message

sequence.cpp: In instantiation of 'static std::vector<int> NTT<mod, root>::mult(const std::vector<int>&, const std::vector<int>&) [with int mod = 998244353; int root = 3]':
sequence.cpp:314:46:   required from here
sequence.cpp:125:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  125 |         for (int i = 0; i < a.size(); i++) {
      |                         ~~^~~~~~~~~~
sequence.cpp:128:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  128 |         for (int i = 0; i < b.size(); i++) {
      |                         ~~^~~~~~~~~~
sequence.cpp:133:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  133 |         for (int i = 0; i < res.size(); i++) {
      |                         ~~^~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 502 ms 79780 KB Output is correct
2 Correct 485 ms 81044 KB Output is correct
3 Correct 494 ms 79460 KB Output is correct
4 Correct 502 ms 79524 KB Output is correct
5 Correct 494 ms 79520 KB Output is correct
6 Correct 491 ms 79560 KB Output is correct
7 Correct 491 ms 79376 KB Output is correct
8 Correct 484 ms 81084 KB Output is correct
9 Correct 492 ms 81252 KB Output is correct
10 Correct 489 ms 80868 KB Output is correct
11 Correct 491 ms 81188 KB Output is correct
12 Correct 497 ms 79516 KB Output is correct
13 Correct 488 ms 79328 KB Output is correct
14 Correct 489 ms 81152 KB Output is correct
15 Correct 490 ms 81264 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 496 ms 79432 KB Output is correct
2 Correct 493 ms 81048 KB Output is correct
3 Correct 489 ms 79556 KB Output is correct
4 Correct 492 ms 79316 KB Output is correct
5 Correct 494 ms 79528 KB Output is correct
6 Correct 489 ms 79408 KB Output is correct
7 Correct 489 ms 80976 KB Output is correct
8 Correct 493 ms 79568 KB Output is correct
9 Correct 488 ms 81120 KB Output is correct
10 Correct 497 ms 81060 KB Output is correct
11 Correct 493 ms 81088 KB Output is correct
12 Correct 492 ms 81016 KB Output is correct
13 Correct 490 ms 81092 KB Output is correct
14 Correct 490 ms 79332 KB Output is correct
15 Correct 503 ms 79804 KB Output is correct
16 Correct 487 ms 81120 KB Output is correct
17 Correct 490 ms 81088 KB Output is correct
18 Correct 495 ms 79532 KB Output is correct
19 Correct 487 ms 80964 KB Output is correct
20 Correct 490 ms 80948 KB Output is correct
21 Correct 492 ms 81060 KB Output is correct
22 Correct 487 ms 81092 KB Output is correct
23 Correct 512 ms 76908 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 504 ms 75816 KB Output is correct
2 Correct 506 ms 81224 KB Output is correct
3 Correct 524 ms 81116 KB Output is correct
4 Correct 540 ms 81252 KB Output is correct
5 Correct 497 ms 81216 KB Output is correct
6 Correct 493 ms 81084 KB Output is correct
7 Correct 945 ms 82072 KB Output is correct
8 Correct 645 ms 81560 KB Output is correct
9 Correct 953 ms 82476 KB Output is correct
10 Correct 953 ms 82624 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 496 ms 79520 KB Output is correct
2 Correct 485 ms 81052 KB Output is correct
3 Correct 495 ms 79408 KB Output is correct
4 Correct 496 ms 79392 KB Output is correct
5 Correct 636 ms 81688 KB Output is correct
6 Correct 497 ms 79412 KB Output is correct
7 Correct 506 ms 79756 KB Output is correct
8 Correct 490 ms 81060 KB Output is correct
9 Correct 497 ms 79376 KB Output is correct
10 Correct 490 ms 80960 KB Output is correct
11 Correct 946 ms 82460 KB Output is correct
12 Correct 951 ms 82536 KB Output is correct
13 Correct 485 ms 80948 KB Output is correct
14 Correct 508 ms 81120 KB Output is correct
15 Correct 487 ms 80980 KB Output is correct
16 Correct 485 ms 81052 KB Output is correct
17 Correct 496 ms 79568 KB Output is correct
18 Correct 492 ms 79424 KB Output is correct
19 Correct 493 ms 80920 KB Output is correct
20 Correct 489 ms 81088 KB Output is correct
21 Correct 491 ms 79520 KB Output is correct
22 Correct 490 ms 81024 KB Output is correct
23 Correct 486 ms 81044 KB Output is correct
24 Correct 494 ms 80992 KB Output is correct
25 Correct 497 ms 81240 KB Output is correct
26 Correct 495 ms 81108 KB Output is correct
27 Correct 487 ms 81256 KB Output is correct
28 Correct 496 ms 81252 KB Output is correct
29 Correct 488 ms 81256 KB Output is correct
30 Correct 492 ms 81096 KB Output is correct
31 Correct 492 ms 81460 KB Output is correct
32 Correct 946 ms 82076 KB Output is correct
33 Correct 639 ms 81732 KB Output is correct
34 Correct 954 ms 82564 KB Output is correct
35 Correct 952 ms 82512 KB Output is correct
36 Incorrect 946 ms 82104 KB Output isn't correct
37 Halted 0 ms 0 KB -