https://atcoder.jp/contests/abc171/tasks
F - Strivore
题意:给定一个字符串s,问有几个长度为n+k的不同的字符串包含这个字符串作为子序列。
计数
关键是不能重复。所以要做出限制。
限制前 n+k−i 个字符中只出现一次串s,而后 i 个字符任意。方法是先选n个位置作为s,再限定s串的第 j 位到第 j+1 位中间这部分不能出现 s[j+1],则必定只出现一次s串。而后 i 位任意。
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; }
|