QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#273694#7876. Cyclic Substringsucup-team180#AC ✓1443ms607100kbC++1713.9kb2023-12-03 03:07:552023-12-03 03:07:55

Judging History

你现在查看的是最新测评结果

  • [2023-12-03 03:07:55]
  • 评测
  • 测评结果:AC
  • 用时:1443ms
  • 内存:607100kb
  • [2023-12-03 03:07:55]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
const long long M30 = ((long long)1 << 30) - 1;
const long long M31 = ((long long)1 << 31) - 1;
const long long MOD = ((long long)1 << 61) - 1;
const long long MOD2 = 998244353;
const long long BASE = 123456789;
unsigned long long modulo(unsigned long long x) {
    unsigned long long xu = x >> 61;
    unsigned long long xd = x & MOD;
    unsigned long long res = xu + xd;
    if(res >= MOD) { res -= MOD; }
    return res;
}
unsigned long long mul(unsigned long long a, unsigned long long b) {
    unsigned long long au = a >> 31;
    unsigned long long ad = a & M31;
    unsigned long long bu = b >> 31;
    unsigned long long bd = b & M31;
    unsigned long long mid = au * bd + ad * bu;
    unsigned long long midu = mid >> 30;
    unsigned long long midd = mid & M30;
    return modulo(au * bu * 2 + midu + (midd << 31) + ad * bd);
}
struct rolling_hash {
    vector<unsigned long long> POW, S;
    rolling_hash(string s) {
        int N = s.size();
        POW.resize(N + 1);
        POW[0] = 1;
        for(int i = 0; i < N; i++) { POW[i + 1] = mul(POW[i], BASE); }
        S.resize(N + 1);
        S[N] = 0;
        for(int i = N - 1; i >= 0; i--) { S[i] = modulo(mul(S[i + 1], BASE) + s[i]); }
    }
    unsigned long long get(int L, int R) { return modulo(S[L] + MOD - mul(S[R], POW[R - L])); }
};
vector<int> manacher(string &S) {
    int N = S.size();
    vector<int> ans(N, 0);
    int i = 0, j = 0;
    while(i < N) {
        while(i >= j && i + j < N && S[i - j] == S[i + j]) { j++; }
        ans[i] = j;
        int k = 1;
        while(i >= k && i + k < N && k + ans[i - k] < j) {
            ans[i + k] = ans[i - k];
            k++;
        }
        i += k;
        j -= k;
    }
    return ans;
}

// https://nyaannyaan.github.io/library/hashmap/hashmap.hpp
namespace HashMapImpl {
using u32 = uint32_t;
using u64 = uint64_t;

template <typename Key, typename Data> struct HashMapBase;

template <typename Key, typename Data> struct itrB : iterator<bidirectional_iterator_tag, Data, ptrdiff_t, Data *, Data &> {
    using base = iterator<bidirectional_iterator_tag, Data, ptrdiff_t, Data *, Data &>;
    using ptr = typename base::pointer;
    using ref = typename base::reference;

    u32 i;
    HashMapBase<Key, Data> *p;

    explicit constexpr itrB() : i(0), p(nullptr) {}
    explicit constexpr itrB(u32 _i, HashMapBase<Key, Data> *_p) : i(_i), p(_p) {}
    explicit constexpr itrB(u32 _i, const HashMapBase<Key, Data> *_p) : i(_i), p(const_cast<HashMapBase<Key, Data> *>(_p)) {}
    friend void swap(itrB &l, itrB &r) { swap(l.i, r.i), swap(l.p, r.p); }
    friend bool operator==(const itrB &l, const itrB &r) { return l.i == r.i; }
    friend bool operator!=(const itrB &l, const itrB &r) { return l.i != r.i; }
    const ref operator*() const { return const_cast<const HashMapBase<Key, Data> *>(p)->data[i]; }
    ref operator*() { return p->data[i]; }
    ptr operator->() const { return &(p->data[i]); }

    itrB &operator++() {
        assert(i != p->cap && "itr::operator++()");
        do {
            i++;
            if(i == p->cap) break;
            if(p->flag[i] == true && p->dflag[i] == false) break;
        } while(true);
        return (*this);
    }
    itrB operator++(int) {
        itrB it(*this);
        ++(*this);
        return it;
    }
    itrB &operator--() {
        do {
            i--;
            if(p->flag[i] == true && p->dflag[i] == false) break;
            assert(i != 0 && "itr::operator--()");
        } while(true);
        return (*this);
    }
    itrB operator--(int) {
        itrB it(*this);
        --(*this);
        return it;
    }
};

template <typename Key, typename Data> struct HashMapBase {
    using u32 = uint32_t;
    using u64 = uint64_t;
    using iterator = itrB<Key, Data>;
    using itr = iterator;

  protected:
    template <typename K> inline u64 randomized(const K &key) const { return u64(key) ^ r; }

    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<K>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K &key) const {
        return (randomized(key) * 11995408973635179863ULL) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr, enable_if_t<is_integral<decltype(K::first)>::value, nullptr_t> = nullptr,
              enable_if_t<is_integral<decltype(K::second)>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K &key) const {
        u64 a = randomized(key.first), b = randomized(key.second);
        a *= 11995408973635179863ULL;
        b *= 10150724397891781847ULL;
        return (a + b) >> shift;
    }
    template <typename K, enable_if_t<is_same<K, Key>::value, nullptr_t> = nullptr,
              enable_if_t<is_integral<typename K::value_type>::value, nullptr_t> = nullptr>
    inline u32 inner_hash(const K &key) const {
        static constexpr u64 mod = (1LL << 61) - 1;
        static constexpr u64 base = 950699498548472943ULL;
        u64 res = 0;
        for(auto &elem : key) {
            __uint128_t x = __uint128_t(res) * base + (randomized(elem) & mod);
            res = (x & mod) + (x >> 61);
        }
        __uint128_t x = __uint128_t(res) * base;
        res = (x & mod) + (x >> 61);
        if(res >= mod) res -= mod;
        return res >> (shift - 3);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr> inline u32 hash(const D &dat) const { return inner_hash(dat); }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr> inline u32 hash(const D &dat) const {
        return inner_hash(dat.first);
    }

    template <typename D = Data, enable_if_t<is_same<D, Key>::value, nullptr_t> = nullptr> inline Key dtok(const D &dat) const { return dat; }
    template <typename D = Data, enable_if_t<is_same<decltype(D::first), Key>::value, nullptr_t> = nullptr> inline Key dtok(const D &dat) const {
        return dat.first;
    }

    void reallocate(u32 ncap) {
        vector<Data> ndata(ncap);
        vector<bool> nf(ncap);
        shift = 64 - __lg(ncap);
        for(u32 i = 0; i < cap; i++) {
            if(flag[i] == true && dflag[i] == false) {
                u32 h = hash(data[i]);
                while(nf[h]) h = (h + 1) & (ncap - 1);
                ndata[h] = move(data[i]);
                nf[h] = true;
            }
        }
        data.swap(ndata);
        flag.swap(nf);
        cap = ncap;
        dflag.resize(cap);
        fill(std::begin(dflag), std::end(dflag), false);
    }

    inline bool extend_rate(u32 x) const { return x * 2 >= cap; }

    inline bool shrink_rate(u32 x) const { return HASHMAP_DEFAULT_SIZE < cap && x * 10 <= cap; }

    inline void extend() { reallocate(cap << 1); }

    inline void shrink() { reallocate(cap >> 1); }

  public:
    u32 cap, s;
    vector<Data> data;
    vector<bool> flag, dflag;
    u32 shift;
    static u64 r;
    static constexpr uint32_t HASHMAP_DEFAULT_SIZE = 4;

    explicit HashMapBase() : cap(HASHMAP_DEFAULT_SIZE), s(0), data(cap), flag(cap), dflag(cap), shift(64 - __lg(cap)) {}

    itr begin() const {
        u32 h = 0;
        while(h != cap) {
            if(flag[h] == true && dflag[h] == false) break;
            h++;
        }
        return itr(h, this);
    }
    itr end() const { return itr(this->cap, this); }

    friend itr begin(const HashMapBase &h) { return h.begin(); }
    friend itr end(const HashMapBase &h) { return h.end(); }

    itr find(const Key &key) const {
        u32 h = inner_hash(key);
        while(true) {
            if(flag[h] == false) return this->end();
            if(dtok(data[h]) == key) {
                if(dflag[h] == true) return this->end();
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    bool contain(const Key &key) const { return find(key) != this->end(); }

    itr insert(const Data &d) {
        u32 h = hash(d);
        while(true) {
            if(flag[h] == false) {
                if(extend_rate(s + 1)) {
                    extend();
                    h = hash(d);
                    continue;
                }
                data[h] = d;
                flag[h] = true;
                ++s;
                return itr(h, this);
            }
            if(dtok(data[h]) == dtok(d)) {
                if(dflag[h] == true) {
                    data[h] = d;
                    dflag[h] = false;
                    ++s;
                }
                return itr(h, this);
            }
            h = (h + 1) & (cap - 1);
        }
    }

    // tips for speed up :
    // if return value is unnecessary, make argument_2 false.
    itr erase(itr it, bool get_next = true) {
        if(it == this->end()) return this->end();
        s--;
        if(shrink_rate(s)) {
            Data d = data[it.i];
            shrink();
            it = find(dtok(d));
        }
        int ni = (it.i + 1) & (cap - 1);
        if(this->flag[ni]) {
            this->dflag[it.i] = true;
        } else {
            this->flag[it.i] = false;
        }
        if(get_next) ++it;
        return it;
    }

    itr erase(const Key &key) { return erase(find(key)); }

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

    int size() const { return s; }

    void clear() {
        fill(std::begin(flag), std::end(flag), false);
        fill(std::begin(dflag), std::end(dflag), false);
        s = 0;
    }

    void reserve(int n) {
        if(n <= 0) return;
        n = 1 << min(23, __lg(n) + 2);
        if(cap < u32(n)) reallocate(n);
    }
};

template <typename Key, typename Data>
uint64_t HashMapBase<Key, Data>::r = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();

} // namespace HashMapImpl

/**
 * @brief Hash Map(base) (ハッシュマップ・基底クラス)
 */

template <typename Key, typename Val> struct HashMap : HashMapImpl::HashMapBase<Key, pair<Key, Val>> {
    using base = typename HashMapImpl::HashMapBase<Key, pair<Key, Val>>;
    using HashMapImpl::HashMapBase<Key, pair<Key, Val>>::HashMapBase;
    using Data = pair<Key, Val>;

    Val &operator[](const Key &k) {
        typename base::u32 h = base::inner_hash(k);
        while(true) {
            if(base::flag[h] == false) {
                if(base::extend_rate(base::s + 1)) {
                    base::extend();
                    h = base::hash(k);
                    continue;
                }
                base::data[h].first = k;
                base::data[h].second = Val();
                base::flag[h] = true;
                ++base::s;
                return base::data[h].second;
            }
            if(base::data[h].first == k) {
                if(base::dflag[h] == true) base::data[h].second = Val();
                return base::data[h].second;
            }
            h = (h + 1) & (base::cap - 1);
        }
    }

    typename base::itr emplace(const Key &key, const Val &val) { return base::insert(Data(key, val)); }
};

/*
 * @brief ハッシュマップ(連想配列)
 * @docs docs/hashmap/hashmap.md
 **/

template <typename Key> struct HashSet : HashMapImpl::HashMapBase<Key, Key> {
    using HashMapImpl::HashMapBase<Key, Key>::HashMapBase;
};

/*
 * @brief ハッシュセット(集合)
 * @docs docs/hashmap/hashset.md
 **/

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    string s;
    cin >> s;
    string s2 = s + s + s;
    string s3;
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < n; j++) {
            s3 += s[j];
            s3 += '$';
        }
    }
    vector<int> M = manacher(s3);
    rolling_hash RH(s2);
    HashSet<unsigned long long> st;
    vector<tuple<int, int, unsigned long long>> P;
    for(int i = n * 2 - 1; i < n * 4 - 1; i++) {
        int l = (i - M[i] + 2) / 2, r = (i + M[i] + 1) / 2;
        if(r - l > n) {
            int x = (r - l - (n - 1)) / 2;
            l += x;
            r -= x;
        }
        while(l < r) {
            long long H = RH.get(l, r);
            if(st.contain(H) == 0) {
                st.insert(H);
                P.push_back(make_tuple(l, r, H));
            } else {
                break;
            }
            l++;
            r--;
        }
    }
    int cnt = P.size();
    sort(P.begin(), P.end(),
         [&](tuple<int, int, unsigned long long> a, tuple<int, int, unsigned long long> b) { return get<1>(a) - get<0>(a) < get<1>(b) - get<0>(b); });

    HashMap<unsigned long long, int> P2;
    // vector<pair<unsigned long long, int>> P2(cnt);
    for(int i = 0; i < cnt; i++) {
        P2[get<2>(P[i])] = i;
        // P2[i] = make_pair(get<2>(P[i]), i);
    }
    // sort(P2.begin(), P2.end());
    vector<int> p(cnt, -1);
    for(int i = 0; i < cnt; i++) {
        if(get<1>(P[i]) - get<0>(P[i]) >= 3) {
            p[i] = P2[RH.get(get<0>(P[i]) + 1, get<1>(P[i]) - 1)];
            // p[i] = (*lower_bound(P2.begin(), P2.end(), make_pair(RH.get(get<0>(P[i]) + 1, get<1>(P[i]) - 1), -1))).second;
        }
    }
    vector<int> imos(cnt, 0);
    for(int i = n * 2 - 1; i < n * 4 - 1; i++) {
        int l = (i - M[i] + 2) / 2, r = (i + M[i] + 1) / 2;
        if(r - l > n) {
            int x = (r - l - (n - 1)) / 2;
            l += x;
            r -= x;
        }
        if(l < r) { imos[P2[RH.get(l, r)]]++; }
    }
    for(int i = cnt - 1; i >= 0; i--) {
        if(p[i] >= 0) { imos[p[i]] += imos[i]; }
    }
    long long ans = 0;
    for(int i = 0; i < cnt; i++) {
        int d = get<1>(P[i]) - get<0>(P[i]);
        if(d <= n) {
            ans += (long long)d * imos[i] % MOD2 * imos[i];
            ans %= MOD2;
        }
    }
    cout << ans << endl;
}

这程序好像有点Bug,我给组数据试试?

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3584kb

input:

5
01010

output:

39

result:

ok 1 number(s): "39"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3636kb

input:

8
66776677

output:

192

result:

ok 1 number(s): "192"

Test #3:

score: 0
Accepted
time: 0ms
memory: 3792kb

input:

1
1

output:

1

result:

ok 1 number(s): "1"

Test #4:

score: 0
Accepted
time: 0ms
memory: 3864kb

input:

2
22

output:

12

result:

ok 1 number(s): "12"

Test #5:

score: 0
Accepted
time: 0ms
memory: 3584kb

input:

2
21

output:

2

result:

ok 1 number(s): "2"

Test #6:

score: 0
Accepted
time: 0ms
memory: 3836kb

input:

3
233

output:

10

result:

ok 1 number(s): "10"

Test #7:

score: 0
Accepted
time: 0ms
memory: 3708kb

input:

3
666

output:

54

result:

ok 1 number(s): "54"

Test #8:

score: 0
Accepted
time: 328ms
memory: 184008kb

input:

1000000
3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333...

output:

496166704

result:

ok 1 number(s): "496166704"

Test #9:

score: 0
Accepted
time: 1094ms
memory: 590936kb

input:

3000000
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222...

output:

890701718

result:

ok 1 number(s): "890701718"

Test #10:

score: 0
Accepted
time: 1087ms
memory: 585664kb

input:

3000000
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999...

output:

224009870

result:

ok 1 number(s): "224009870"

Test #11:

score: 0
Accepted
time: 1025ms
memory: 590252kb

input:

3000000
8989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989...

output:

51985943

result:

ok 1 number(s): "51985943"

Test #12:

score: 0
Accepted
time: 1070ms
memory: 589672kb

input:

3000000
1911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911911...

output:

355676465

result:

ok 1 number(s): "355676465"

Test #13:

score: 0
Accepted
time: 1443ms
memory: 603868kb

input:

3000000
7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777...

output:

788510374

result:

ok 1 number(s): "788510374"

Test #14:

score: 0
Accepted
time: 1407ms
memory: 607100kb

input:

3000000
5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555...

output:

691884476

result:

ok 1 number(s): "691884476"

Test #15:

score: 0
Accepted
time: 864ms
memory: 589164kb

input:

3000000
0990990909909909099090990990909909909099090990990909909099099090990990909909099099090990990909909099099090990909909909099099090990909909909099090990990909909909099090990990909909909099090990990909909099099090990990909909099099090990990909909099099090990909909909099099090990909909909099090990...

output:

701050848

result:

ok 1 number(s): "701050848"

Test #16:

score: 0
Accepted
time: 434ms
memory: 344160kb

input:

3000000
2772772727727727277272772772727727727277272772772727727277277272772772727727277277272772772727727277277272772727727727277277272772727727727277272772772727727727277272772772727727727277272772772727727277277272772772727727277277272772772727727277277272772727727727277277272772727727727277272772...

output:

486861605

result:

ok 1 number(s): "486861605"

Test #17:

score: 0
Accepted
time: 1086ms
memory: 600228kb

input:

3000000
4554554545545545455454554554545545545455454554554545545455455454554554545545455455454554554545545455455454554545545545455455454554545545545455454554554545545545455454554554545545545455454554554545545455455454554554545545455455454554554545545455455454554545545545455455454554545545545455454554...

output:

450625621

result:

ok 1 number(s): "450625621"

Test #18:

score: 0
Accepted
time: 1089ms
memory: 596476kb

input:

3000000
1181811811818118181181181811818118118181181181811818118118181181181811818118118181181811811818118118181181811811818118181181181811811818118181181181811811818118181181181811818118118181181181811818118118181181181811818118118181181811811818118118181181811811818118181181181811811818118181181181...

output:

649551870

result:

ok 1 number(s): "649551870"

Extra Test:

score: 0
Extra Test Passed