2021牛客寒假集训营第一场-A串
串
链接:https://ac.nowcoder.com/acm/contest/9981/A
来源:牛客网
题目描述
长度不超过nnn,且包含子序列“us”的、只由小写字母构成的字符串有多少个? 答案对10^9+7取模。
所谓子序列,指一个字符串删除部分字符(也可以不删)得到的字符串。
例如,"unoacscc"包含子序列"us",但"scscucu"则不包含子序列"us"
输入描述:
一个正整数n(2≤n≤10^6)
输出描述:
一个正整数,为满足条件的字符串数量对10^9+7取模的值
解题思路
看似是用排列组合求方法数的题,但是实际上这道题用dp可以轻松的解决。
定义数组二维数组f[1000100][3],将长度为i的字符串统计三种类型
① f[i][0] 前i个字符,已含有us字串的数量
② f[i][1] 前i个字符,含有u但不含有s的数量
③ f[i][2] 前i个字符,不含有u的数量
初始状态下
f[1][0] = 0; f[1][1] = 1; f[1][2] = 25;
① = ① * 26 + ② ① = ①前i-1个加任意字符 + ②前i-1加字符s
② = ② * 25 + ③ ② = ②前i-1个加除s外的任意字符 + ③前i-1加字符u
③ = ③ * 25 ③ = ③前i-1个加除u外的任意字符
可得到以下状态转移方程
f[i][0] = (f[i - 1][0] * 26 + f[i - 1][1]) % mod; f[i][1] = (f[i - 1][1] * 25 + f[i - 1][2]) % mod; f[i][2] = (f[i - 1][2]*25) % mod;
最后输出f[1..n][0]的和模1e9 + 7即为所求答案
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 using ll = long long; 4 5 const int mod = 1e9 + 7; 6 7 ll f[2000000][3]; 8 int main() 9 { 10 ios::sync_with_stdio(false); 11 cin.tie(0); 12 int n; 13 cin >> n; 14 15 f[1][0] = 0; 16 f[1][1] = 1; 17 f[1][2] = 25; 18 19 for (int i = 2; i <= n; i++) 20 { 21 f[i][0] = (f[i - 1][0] * 26 + f[i - 1][1]) % mod; 22 f[i][1] = (f[i - 1][1] * 25 + f[i - 1][2]) % mod; 23 f[i][2] = (f[i - 1][2]*25) % mod; 24 } 25 ll ans=0; 26 for (int i = 0; i <= n; i++) 27 ans = (ans + f[i][0]) % mod; 28 cout << ans; 29 return 0; 30 }