https://atcoder.jp/contests/abc171/tasks

F - Strivore

 

题意:给定一个字符串s,问有几个长度为n+k的不同的字符串包含这个字符串作为子序列。

计数

关键是不能重复。所以要做出限制。

限制前 n+kin+k-i 个字符中只出现一次串s,而后 ii 个字符任意。方法是先选n个位置作为s,再限定s串的第 jj 位到第 j+1j+1 位中间这部分不能出现 s[j+1]s[j+1],则必定只出现一次s串。而后 ii 位任意。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int N = 2e6 + 10;
char s[N];
int n, k;
ll fac[N], inv[N];
ll power(ll a, int x) {
ll ans = 1;
while (x) {
if (x & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
x >>= 1;
}
return ans;
}
void init() {
fac[0] = 1;
for (int i = 1; i < N; i++) {
fac[i] = fac[i - 1] * i %mod;
}
inv[N - 1] = power(fac[N - 1], mod - 2);
for (int i = N - 2; i >= 0; i--) {
inv[i] = inv[i + 1] * (i + 1) % mod;
}
}
ll C(int n, int k) {
return fac[n] * inv[k] % mod*inv[n - k] % mod;
}
int main() {
scanf("%d", &k);
scanf("%s", s);
n = strlen(s);
init();
ll ans = 0;
for (int i = 0; i <= k; i++) {
ans = (ans + power(26, i)*C(n + k - i - 1, n - 1) % mod*power(25, k - i) % mod) % mod;
}
printf("%lld\n", ans);
return 0;
}