题意:有一个字符串 T T T ,问有多少种长度为 m m m 的字符串,满足 T T T 是其子序列。
思路:枚举 T T T 最后一个字符作为子串在长度为 m m m 的字符串 s s s 中出现的位置 p o s pos pos ,对于每种情况,求最后一个字符除外在字符串 s s s 中位置的组合数,这相当于把 p o s pos pos 之前的分成了 T . s i z e ( ) T.size() T.size() 段,每段中间则不能出现与后一段间隔的字符:比如 T T T 中存在有一个字符 a a a ,其中一种组合是 _ _ a _ _,则前两个空则不能出现 a a a。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
#define mod 1000000007
int inv[100005], mul[100005];
int m, len, fac[100005];
string s;
inline int c(const int &x, const int &y)
{
return 1LL * mul[x] * fac[y] % mod * fac[x - y] % mod;
}
inline int ppow(int x, int y)
{
if (y == 0)
return 1;
int ans = 1;
while (y)
{
if (y & 1)
{
ans = 1LL * ans * x % mod;
--y;
}
else
{
x = 1LL * x * x % mod;
y >>= 1;
}
}
return ans;
}
int main()
{
cin >> s, len = s.size();
scanf("%d", &m);
if (len > m)
{
printf("0\n");
return 0;
}
if (len == m)
{
printf("1\n");
return 0;
}
fac[1] = inv[1] = mul[1] = fac[0] = inv[0] = mul[0] = 1;
for (int i = 2; i <= m; ++i)
{
mul[i] = 1LL * mul[i - 1] * i % mod;
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
fac[i] = 1LL * fac[i - 1] * inv[i] % mod;
}
int ans = ppow(26, m - len);
for (int i = len + 1; i <= m; ++i) //枚举T最后一位出现的位置
(ans += (((1LL * c(i - 1, len - 1) * ppow(25, i - len) % mod) * 1LL * ppow(26, m - i)) % mod)) %= mod;
printf("%d\n", ans);
return 0;
}