日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P2167 [SDOI2009]Bill的挑战

發布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P2167 [SDOI2009]Bill的挑战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

P2167 [SDOI2009]Bill的挑戰

題意:

有n個長度一樣的字符串,字符串的每一位是?或者確定的字母,,求與這 N 個串中的剛好 K 個串匹配的字符串 T 的個數
1<=N<=15,1<=|S|<=50

題解:

很明顯狀態dp
我們可以先預處理一個match[1…len][a…z]:表示第i位取ch的狀態,比如match[1]['a]=10101就表示第一個,第三個,第五個字符串的第一位可以取’a‘。預處理出match
f[i][j]表示第i位的匹配上了j這個狀態的方案數
轉移方程:
j=1010(二進制)就表示:選了第2行和第四行的字符串的狀態
選在第i+1行時,要與第i行的狀態取&

int now= (match[i][ch - 'a'] & j); f[i + 1][now]= (f[i + 1][now] + f[i][j]) % mod;

最后枚舉答案時,因為題目有說時選取k行,所以枚舉所有狀態,只有狀態中帶有k個1的是我們要的狀態

代碼:

// Problem: P2167 [SDOI2009]Bill的挑戰 // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P2167 // Memory Limit: 125 MB // Time Limit: 1000 ms // Data:2021-08-11 21:21:14 // By Jozky#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; template <typename T> inline void read(T& x) {T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f; } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn= 100; char s[maxn][maxn]; const int mod= 1e6 + 3; int f[60][1 << 15]; int match[60][60]; int main() {//rd_test();int t;read(t);while (t--) {memset(f, 0, sizeof(f));memset(match, 0, sizeof match);int tot= 0;int n, k;cin >> n >> k;for (int i= 1; i <= n; i++)scanf("%s", s[i]);int len= strlen(s[1]);for (int i= 0; i < len; i++) { //對于每一位for (char ch= 'a'; ch <= 'z'; ch++) {for (int k= 1; k <= n; k++) { //對于每個字符串//第k個字符串的第i個位置if (s[k][i] == '?' || s[k][i] == ch) {match[i][ch - 'a']|= (1 << (k - 1));//第i位取ch的狀態}}}}int cnt= (1 << n) - 1;f[0][cnt]= 1; //初始狀態for (int i= 0; i < len; i++) {for (int j= 0; j <= cnt; j++) {if (f[i][j]) { //如果f第i個位置的j狀態有方案for (char ch= 'a'; ch <= 'z'; ch++) {//得到新狀態int now= (match[i][ch - 'a'] & j);f[i + 1][now]= (f[i + 1][now] + f[i][j]) % mod;}}}}for (int i= 0; i <= cnt; i++) { //枚舉取字符串的所有狀態int ans= 0;for (int j= 1; j <= cnt; j<<=1)ans+= (bool)(i&j);if (ans == k) //如果取了k個字符串(i中有k個1)tot= (tot + f[len][i]) % mod;}printf("%d\n", tot);}//Time_test(); }

總結

以上是生活随笔為你收集整理的P2167 [SDOI2009]Bill的挑战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。