题目
描述
We consider a string to be a good string if and only if the string contains no palindromic substrings of length greater than 2
Now we want to know how many different good strings are there for all strings of exactly n length and character set size m (not all characters in the character set are used).
一个好串的定义是当且仅当它不包含长度超过2的回文子串,给定整数n,m,n 表示字符串的长度,m 表示字符集合的大小,找出长度为n的不同的好串的个数
输入
Only one line contains two integer n, m(1 < n < 106, 1 < m ≤109).
输出
Output a integer is number of different good strings,the answer is modulo 1000000007.
Sample Input 1
3 3
Sample Output 1
18
代码长度限制 16KB
时间限制 1000ms
内存限制 256 MB
分析
好串不能有如下子结构:
xyx
:回文串长度为 3xyyx
:回文串长度为 4
好串最后三位可以有的子结构:
- 结构0:
xyz
:x、y、z 互不相同,dp[i][0] - 结构1:
xxy
:x、y 不同,dp[i][1] - 结构2:
xyy
:x、y 不同,dp[i][2]
特殊情况
if (n == 1) {
return m;
}
// 其实可以归于 n == 2 return m+m*(m-1)
if (n == 2 && m == 1) {
return 1;
}
if (n == 2 && m >= 2) {
return m+m*(m-1);
}
// 其实可以直接使用转移方程了
if (m == 1 && n >= 3) {
return 0;
}
if (m == 2 && n == 3) {
return 4;
}
转移方程
// dp[i][0] 表示长度为 i 且最后三个字母是 xyz 的好串个数
// dp[i][1] 表示长度为 i 且最后三个字母是 xyy 的好串个数
// dp[i][2] 表示长度为 i 且最后三个字母是 xxy 的好串个数
// dp[i-1][0] xyz --> yz[k] k除了x、y有 m-2 种选法
// dp[i-1][1] xxy --> xy[k] k除了x、y有 m-2 种选法
// dp[i-1][2] xyy --> yy[k] 无法得到结构0
dp[i][0] = dp[i-1][0]*(m-2) + dp[i-1][1]*(m-2);
// dp[i-1][0] xyz --> yz[k] 无法得到结构1
// dp[i-1][1] xxy --> xy[k] 无法得到结构1
// dp[i-1][2] xyy --> yy[k] k除了y有 m-1 种选法
dp[i][1] = dp[i-1][2]*(m-1);
// dp[i-1][0] xyz --> xy[k] k只能选择y
// dp[i-1][1] xxy --> xy[k] k只能选择y
// dp[i-1][2] xyy --> yy[k] 无法得到结构2
dp[i][2] = dp[i-1][0] + dp[i-1][1];
代码
#include <iostream>
using namespace std;
int main()
{
int mod = 1e9+7;
int n, m;
cin >> n >> m;
if (n == 1) {
cout << m;
return 0;
}
if (n == 2) {
cout << m + m*(m-1);
return 0;
}
// dp[i][0] 表示长度为 i 且最后三个字母是 xyz 的好串个数
// dp[i][1] 表示长度为 i 且最后三个字母是 xyy 的好串个数
// dp[i][2] 表示长度为 i 且最后三个字母是 xxy 的好串个数
int dp[n+1][3];
dp[3][0] = m*(m-1)*(m-2);
dp[3][1] = m*(m-1);
dp[3][2] = m*(m-1);
for (int i = 4; i <= n; ++ i) {
dp[i][0] = (dp[i-1][0]*(m-2) + dp[i-1][1]*(m-2)) % mod;
dp[i][1] = dp[i-1][2]*(m-1) % mod;
dp[i][2] = (dp[i-1][0] + dp[i-1][1]) % mod;
}
cout << (dp[n][0] + dp[n][1] + dp[n][2]) % mod;
return 0;
}