题意: 给定一个字符串
S
S
S,问插入
k
k
k个字符后可以形成多少个不同的字符串,答案对
1
0
9
+
7
10^9+7
109+7取模。
题解: 设字符串
S
S
S长度为
l
e
n
len
len,当插入了
k
k
k个字符后长度变为
l
e
n
+
k
len+k
len+k,故我们可以枚举字符串
S
S
S的
l
e
n
len
len个字符位置。
- 枚举 i i i为字符串 S S S中 S [ l e n − 1 ] S[len-1] S[len−1]这个字符(最后一个字符)的位置,那么之后的 l e n + k − i len+k-i len+k−i个字符每个都有 26 26 26个选择,即 2 6 l e n + k − i 26^{len+k-i} 26len+k−i种。
- 那么对于前面 i − 1 i-1 i−1个字符,(第 i i i个字符已经确定),我们先选择其中 l e n − 1 len-1 len−1个位置作为 S S S的前 l e n − 1 len-1 len−1个字符,则剩下的 i − l e n i-len i−len个则只有25种选择。至于这 i − l e n i-len i−len个只有25种就是如下图中 [ [ [^ S i ] {S_i}] Si]的这种字符,因为如果在 S i S_i Si和 S i − 1 S_{i-1} Si−1间的 x x x这个位置出现了 S i S_i Si,那么相当于将这个 S i S_i Si的位置选择在了 x x x,后面的又是根据 S i + 1 S_{i+1} Si+1来选择了。
- 换种方式理解 2 2 2:这个过程可以看出 d p dp dp的状态转移。那么我们考虑 S S S中最后一个字符 S [ l e n − 1 ] S[len-1] S[len−1]的位置,由 1 1 1可知道当确定了 S [ l e n − 1 ] S[len-1] S[len−1]的位置后,其后面的所有字符有 26 26 26种选择,所以当我们在 S l e n − 2 S_{len-2} Slen−2和 S l e n − 1 S_{len-1} Slen−1中插入了一个和 S l e n − 1 S_{len-1} Slen−1相同的字符,相当于将 S l e n − 1 S_{len-1} Slen−1的位置前移了,那么就是另一种情况了。所以枚举的前 i i i个字符中的 i − l e n i-len i−len个字符有 25 25 25种情况。
戳我进官方题解
下图是官方题解图:
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
ll fac[N], inv[N];
char s[N];
int k;
ll qp(ll a, ll b) {
ll res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
void init() {
fac[0] = fac[1] = 1;
for(int i = 2; i < N; i++) fac[i] = fac[i - 1] * i % mod;
inv[N - 1] = qp(fac[N - 1], mod - 2);
for(int i = N - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll C(ll a, ll b) {
if(b > a) return 0ll;
return fac[a] * inv[b] % mod * inv[a - b] % mod;
}
ll add(ll a, ll b) {
return (a + b) % mod;
}
int main()
{
init();
scanf("%d", &k);
scanf("%s", s);
ll res = 0;
int len = strlen(s);
for(int i = len; i <= k + len; i++) //枚举前i个字符为S的所在地,即第i个位置是字符s[len-1]的所在地
res = add(res, C(i - 1, len - 1) * qp(25ll, i - len) % mod * qp(26ll, k + len - i) % mod);
printf("%lld\n", res);
return 0;
}