我们称一个字符串是优美的,当且仅当这个字符串中不存在长度严格大于 2 的回文串。
现在有 m 种不同的字符,那么在可以组成的长度恰好为 n 的 m^n 个不同的字符串中,请求出一共有多少个字符串是优美的,输出答案对 1000000007 取模后的结果即可。
字符串中不能存在严格大于2的回文串,则每相邻的三个字符都不能是回文串。三个字符非回文的情况有三aab abb abc。围绕此三种情况进行思考即可。
可以向动态规划的思想上靠拢(当时也没怎么往这边想)
定义集合f[i][3]:
f[i][0]:以i结尾,最后三个字符为 abc类的方案的集合
f[i][1]:以i结尾,最后三个字符为 aab类的方案的集合
f[i][2]:以i结尾,最后三个字符为 abb类的方案的集合
根据三种状态的特点我们可以得到状态转移方程
f[i][0] = f[i - 1][1] * (m - 2) + f[i - 1][0] * (m - 2)
f[i][1] = f[i - 2][0] * (m - 2)
f[i][2] = f[i - 1][0] + f[i - 1][1];
值得注意的是,当n<3时的情况需要特判
n == 1时,方案数为mn == 2时,方案数为 m + m * (m - 1) 即m * m 值得注意的是取模一定要细心
#includeusing namespace std;const int N = 1e6 + 10, mod = 1000000007;
typedef long long ll;ll n, m, k, t;
ll f[N][3];int main()
{cin >> n >> m;if(n < 3){if(n == 1) cout << m << "\n";else{ll ans = m * m % mod;cout << ans % mod << "\n";}return 0;}f[3][0] = m * (m - 1) % mod * (m - 2) % mod;f[3][1] = f[3][2] = m * (m - 1) % mod;for(int i = 4; i <= n; i ++){f[i][0] = (f[i - 1][1] * (m - 2)) % mod + (f[i - 1][0] * (m - 2) % mod);f[i][1] = f[i - 1][2] * (m - 2) % mod;f[i][2] = (f[i - 1][0] % mod) + (f[i - 1][1] % mod) % mod;}cout << (f[n][0] + f[n][1] + f[n][2]) % mod << "\n";return 0;
}