AtCoder Beginner Contest 215 E - Chain Contestant
生活随笔
收集整理的這篇文章主要介紹了
AtCoder Beginner Contest 215 E - Chain Contestant
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
AtCoder Beginner Contest 215 E - Chain Contestant
給出一個只包括A~J的字符串,定義一種子序列為:在這個子序列中,相同的字符必定連續出現,求出這樣的子序列有多少個。
數據范圍:字符串長度1 <= n <= 1000
看起來就是一道狀壓dp,但是寫得不是很順利,所以在這里回顧一下。
定義dpi,j,kdp_{i,j,k}dpi,j,k?為,到字符串的第i位,出現過j種類的字符(j是狀態壓縮),目前最后的一位為k。
狀態轉移的時候,我們可以認為當前位置有選擇或者不選擇兩種情況,如果是不選擇的話,那么當前位置的每一個狀態的方案數都和上一個位置的方案數相同,先預處理出來。如果選擇的話,先把前面是空串的方案加1,然后枚舉出現過當前字符的狀態,之后再討論是從哪種狀態所轉移過來的,如果之前的結尾和當前字符相同,那么就是相同的狀態轉移過來;如果不同,那么狀態就要減去當前的這個字符。
由于i從i-1轉移過來,所以可以用滾動數組優化空間。
時間復雜度O(MN2M)O(MN2^M)O(MN2M),M為字符種類數
#include <bits/stdc++.h> #define f(i, n) for(int i = 1; i <= n; i ++) #define nf(i, n) for(int i = n; i >= 1; i --) typedef long long ll; using namespace std;const int N = 1010, mod = 998244353; char str[N]; long long dp[2][(1 << 10) + 10][10];int charToNum(char c) {return c - 'A'; }int main() {//freopen("in.txt", "r", stdin);ios::sync_with_stdio(false);cin.tie(0);int T = 1;//cin >> T;while (T --){int n;cin >> n;cin >> str;int len = strlen(str), flag = 0;dp[0][(1 << charToNum(str[0]))][charToNum(str[0])] = 1;for (int i = 1; i < len; i ++){ flag ^= 1;for (int j = 0; j < (1 << 10); j ++)for (int k = 0; k < 10; k ++)if (j & (1 << k))dp[flag][j][k] = dp[flag ^ 1][j][k];int num = charToNum(str[i]);dp[flag][(1 << num)][num] += 1;for (int j = 0; j < (1 << 10); j ++)if (j & (1 << num))for (int k = 0; k < 10; k ++){if (k == num)dp[flag][j][num] += dp[flag ^ 1][j][k];elsedp[flag][j][num] += dp[flag ^ 1][j - (1 << num)][k];dp[flag][j][num] %= mod;}}long long ans = 0;for (int j = 0; j < (1 << 10); j ++)for (int k = 0; k < 10; k ++)ans = (ans + dp[flag][j][k]) % mod;cout << ans;}return 0; }總結
以上是生活随笔為你收集整理的AtCoder Beginner Contest 215 E - Chain Contestant的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mysql中用between...and
- 下一篇: sudo mysql压缩备份解压操作_高