萌新求助,这联考T2又卡哈希又卡常,如何优化

题目总版

JPGOJCZX @ 2024-11-15 20:44:52

已经卡了 1 坤天了。

原题:CF GYM 102769J Jewel Splitting

#define LOCAL
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#define int long long
#define pc putchar
#define gc getchar
namespace IO{
    #ifndef LOCAL
        #define SIZE (1 << 20)
        char buf1[SIZE], buf2[SIZE], *p1 = buf1, *p2 = buf1, *p3 = buf2;
        #define gc() (p1 == p2 && (p2 = (p1 = buf1) + fread(buf1, 1, SIZE, stdin), p1 == p2) ? EOF : *p1++)
        #define flush() (fwrite(p3 = buf2, 1, SIZE, stdout))
        #define pc(ch) (p3 == buf2 + SIZE && flush(), *p3++ = (ch))
        class Flush{public : ~ Flush(){flush();}}_;
    #endif
    template <typename type>
    inline void rd(type &x){
        x = 0; bool f(0); char c = gc();
        while(!isdigit(c))f ^= c == '-', c = gc();
        while(isdigit(c))x = (x << 3) + (x << 1) + (c ^ 48), c = gc();
        f ? x = - x : 0;
    }
    template <typename type>
    inline void wt(type x){
        x < 0 ? x = - x, pc('-') : 0; static short st[50], top(0);
        do st[++top] = x % 10, x /= 10; while(x);
        while(top)pc(st[top--] ^ 48);
    }
    inline char rd(char &c){return c = gc();}
    inline char wt(const char &c){return pc(c);}
    template <typename type, typename ...T>
    inline void rd(type &x, T &...y){rd(x), rd(y...);}
    template <typename type, typename ...T>
    inline void wt(type x, T ...y){wt(x), pc(' '), wt(y...), sizeof ...(y) ^ 1 ? 0 : pc('\n');}
    #ifndef LOCAL
        #undef SIZE
        #undef gc
        #undef pc
        #undef flush
    #endif
}
using namespace IO;
using namespace std;
using namespace __gnu_pbds;
const int N = 3e5 + 9;
inline int extend_gcd(int a, int b, int &x, int &y){
    if(b == 0){
        x = 1;
        y = 0;
        return 0;
    }
    int d = extend_gcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
inline int mod_inverse(int a, int m){
    int x, y;
    extend_gcd(a, m, x, y);
    return (x % m + m) % m;
}
int B[N], H[N], base = 131, MOD1 = 998244353, MOD2 = (1ll << 61) - 1;
inline __int128 sub(__int128 x, __int128 y){
    return x - y < 0 ? x - y + MOD2 : x - y;
}
inline __int128 mod(__int128 x){
    return sub((MOD2 & x) + (x >> 61), MOD2);
}
inline __int128 Hash(int l, int r){
    return mod(sub(__int128(H[r]), mod(__int128(H[l - 1]) * __int128(B[r - l + 1]))));
}
int T, n, ans, ji[N], inv[N], cnt = 1;
char ch[N];
inline void solve(){
    ans = 0;
    gp_hash_table <int, bool> h2{};
    scanf("%s", ch + 1);
    n = strlen(ch + 1);
    B[0] = 1;
    for(register int i = 1; i <= n; ++i){
        H[i] = mod(mod(__int128(H[i - 1]) * __int128(base)) + ch[i]);
        B[i] = mod(__int128(B[i - 1]) * __int128(base));
    }
    for(register int d = 1; d <= n; ++d){
        gp_hash_table <unsigned long long, int> h1{};
        int quo = n / d, rem = n % d, val = ji[quo];
        unsigned long long tmp = 0;
        for(register int i = rem + 1; i <= n; i += d){
            __int128 num = Hash(i, i + d - 1);
            tmp += mod(num * num * num * num);
            if(h1[num])
                val = val * ji[h1[num]] % MOD1;
            h1[num]++;
            val = val * inv[h1[num]] % MOD1;
        }
        if(!h2[tmp]){
            h2[tmp] = true;
            ans = (ans + val) % MOD1;
        }
        for(register int k = 1; k <= quo; ++k){
            __int128 num1 = Hash((k - 1) * d + rem + 1, k * d + rem), num2 = Hash((k - 1) * d + 1, k * d);
            val = val * ji[h1[num1]] % MOD1;
            if(h1[num2] != 0)
                val = val * ji[h1[num2]] % MOD1;
            h1[num1]--;
            h1[num2]++;
            if(h1[num1] != 0)
                val = val * inv[h1[num1]] % MOD1;
            val = val * inv[h1[num2]] % MOD1;
            tmp += mod(num2 * num2 * num2 * num2) - mod(num1 * num1 * num1 * num1);
            if(h2[tmp])
                continue;
            h2[tmp] = true;
            ans = (ans + val) % MOD1;
        }
    }
    pc('C');
    pc('a');
    pc('s');
    pc('e');
    pc(' ');
    pc('#');
    wt(cnt);
    pc(':');
    pc(' ');
    wt(ans % MOD1);
    pc('\n');
    cnt++;
}
signed main(){
    ji[1] = 1;
    for(register int i = 2; i < N; ++i)
        ji[i] = ji[i - 1] * i % MOD1;
    inv[N - 1] = mod_inverse(ji[N - 1], MOD1);
    for(register int i = N - 2; i >= 1; --i)
        inv[i] = inv[i + 1] * (i + 1) % MOD1;
    rd(T);
    while(T--)
        solve();
    return 0;
}

玄关qwq


|