考虑发现答案为对于原串的每个 border 长度
原理基于 有哪些有趣的概率问题?。
xxxxxxxxxx71123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23template < typename T = int >24inline T read(void);25
26int N, M;27int vals[110000];28int nxt[110000];29ll powN[110000];30ll ans(0);31
32int main(){powN[0] = 1;33 N = read();34 for(int i = 1; i <= 101000; ++i)powN[i] = powN[i - 1] * N % 10000;35 int T = read();36 while(T--){37 M = read();38 ans = powN[M];39 for(int i = 1; i <= M; ++i)vals[i] = read();40 int lst(0);41 nxt[0] = nxt[1] = 0;42 for(int i = 2; i <= M; ++i){43 while(lst && vals[lst + 1] != vals[i])lst = nxt[lst];44 if(vals[lst + 1] == vals[i])++lst;45 nxt[i] = lst;46 }int cur(nxt[M]);47 while(cur)48 (ans += powN[cur]) %= 10000,49 cur = nxt[cur];50 printf("%04lld\n", ans);51 }52
53 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);54 return 0;55}56
57template < typename T >58inline T read(void){59 T ret(0);60 int flag(1);61 char c = getchar();62 while(c != '-' && !isdigit(c))c = getchar();63 if(c == '-')flag = -1, c = getchar();64 while(isdigit(c)){65 ret *= 10;66 ret += int(c - '0');67 c = getchar();68 }69 ret *= flag;70 return ret;71}纯组合意义是不可能的,这辈子都不可能的。
发现本质不同关键字,不难想到群论,对于本题可以使用 Burnside,考虑令
考虑经典转化,即
转化为:
考虑处理
即经典插板法。
则对于
同时注意对于
xxxxxxxxxx97123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
232425
26template < typename T = int >27inline T read(void);28
29int N, M, K;30ll phi[LIM + 100];31bitset < LIM + 100 > notPrime;32basic_string < int > Prime;33ll fact[LIM + 100], inv[LIM + 100];34
35int main(){36 auto qpow = [](ll a, ll b)->ll{37 ll ret(1), mul(a);38 while(b){39 if(b & 1)ret = ret * mul % MOD;40 b >>= 1;41 mul = mul * mul % MOD;42 }return ret;43 };44 auto Init = [qpow](void)->void{45 phi[1] = fact[0] = 1;46 for(int i = 2; i <= LIM; ++i){47 if(!notPrime[i])phi[i] = i - 1, Prime += i;48 for(auto p : Prime){49 if((ll)i * p > LIM)break;50 notPrime[i * p] = true;51 if(i % p == 0)phi[i * p] = p * phi[i] % MOD;52 else phi[i * p] = phi[p] * phi[i] % MOD;53 if(i % p == 0)break;54 }55 }56 for(int i = 1; i <= LIM; ++i)fact[i] = fact[i - 1] * i % MOD;57 inv[LIM] = qpow(fact[LIM], MOD - 2);58 for(int i = LIM - 1; i >= 0; --i)inv[i] = inv[i + 1] * (i + 1) % MOD;59 };Init();60 auto GetC = [](ll n, ll m)->ll{61 if(n < m || n < 0 || m < 0)return 0;62 return fact[n] * inv[m] % MOD * inv[n - m] % MOD;63 };64 auto Cal = [qpow, GetC](ll N, ll M, ll K)->ll{65 ll ret(0);66 for(int i = 0, flag = 1; i * (K + 1) <= M; ++i, flag *= -1)67 (ret += ((flag * GetC(N, i) * GetC(M - i * (K + 1) + N - 1, N - 1) % MOD) + MOD) % MOD) %= MOD;68 (ret *= (N + M) * qpow(N, MOD - 2) % MOD) %= MOD;69 return ret;70 };71 ll ans(0);72 N = read(), M = read(), K = read();73 if(N == M)printf("%d\n", K >= N ? 1 : 0), exit(0);74 for(int i = 1; i <= N; ++i)75 if(N % i == 0 && M % i == 0)76 (ans += Cal((N - M) / i, M / i, K) * phi[i] % MOD) %= MOD;77 (ans *= qpow(N, MOD - 2)) %= MOD;78 printf("%lld\n", ans);79 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);80 return 0;81}82
83template < typename T >84inline T read(void){85 T ret(0);86 int flag(1);87 char c = getchar();88 while(c != '-' && !isdigit(c))c = getchar();89 if(c == '-')flag = -1, c = getchar();90 while(isdigit(c)){91 ret *= 10;92 ret += int(c - '0');93 c = getchar();94 }95 ret *= flag;96 return ret;97}update-2023_03_06 初稿