題目簡述spa
給定一個H×W大小的矩陣,每一個格子要麼是1~9中的一個數,要麼是".",要求你把「.」填成具體的數字(1~9),而且符合如下兩個要求:設計
題解code
咱們能夠發現F[r][c]和 F[r+n][c]的奇偶性是同樣的,一樣F[r][c]和F[c+m]也是一樣的奇偶性,那麼咱們能夠把F[r+p*n][c+q*m]的能夠放的奇數和偶數的個數統計到odd[r][c]和even[r][c]中,矩陣就壓縮成了n*m了!注意若是F[r+p*n][c+q*m]是個肯定的數,若是是奇數,那麼even[r][c]=0,反之odd[r][c]=0.blog
這樣問題就轉化成了求n×m的矩陣,每行和每列的和都是奇數的方案數!get
接下來咱們先預處理出每一行都是奇數和的狀態的方案數cnt[i][mask],而後再進行DP,方程是dp[i][mask1^maks2]+=dp[i-1][mask1]*cnt[i][maks2],第i-1行的列狀態數是mask1,第i行選取的行狀態是mask2,那麼造成的列狀態就是mask1^maks2,最後的答案就是dp[n][(1<<m)-1],(1<<m)-1剛好表示每一列的狀態都是奇數。這道題真是很贊,狀態設計好巧妙~~,徹底想不到啊!string
代碼:it
1 typedef long long LL; 2 #define MOD 1000000007 3 LL odd[15][15], even[15][15]; 4 LL dp[15][1 << 12], cnt[15][1 << 12]; 5 class MagicalGirlLevelTwoDivOne 6 { 7 public: 8 int go(int num) 9 { 10 int ret = 0; 11 while (num) 12 { 13 ret += num & 1; 14 num >>= 1; 15 } 16 return ret; 17 } 18 int theCount(vector <string> palette, int n, int m) 19 { 20 int x = palette.size(), y = palette[0].size(); 21 for (int i = 0; i < n; i++) 22 for (int j = 0; j < m; j++) odd[i][j] = even[i][j] = 1; 23 for (int i = 0; i < x; i++) 24 for (int j = 0; j < y; j++) 25 { 26 if (palette[i][j] == '.') 27 { 28 odd[i % n][j % m] *= 5; 29 odd[i % n][j % m] %= MOD; 30 even[i % n][j % m] *= 4; 31 even[i % n][j % m] %= MOD; 32 } 33 else 34 { 35 int num = palette[i][j] - '0'; 36 if (num % 2 == 0) odd[i % n][j % m] = 0; 37 else even[i % n][j % m] = 0; 38 } 39 } 40 memset(cnt, 0, sizeof(cnt)); 41 for (int i = 0; i < n; i++) 42 for (int mask = 0; mask < (1 << m); mask++) 43 { 44 int tot = go(mask); 45 if (tot % 2 == 0) continue; 46 cnt[i][mask] = 1; 47 for (int j = 0; j < m; j++) 48 { 49 if (mask & (1 << j)) 50 cnt[i][mask] *= odd[i][j]; 51 else cnt[i][mask] *= even[i][j]; 52 cnt[i][mask] %= MOD; 53 } 54 } 55 memset(dp, 0, sizeof(dp)); 56 dp[0][0] = 1; 57 for (int i = 1; i <= n; i++) 58 for (int mask1 = 0; mask1 < (1 << m); mask1++) 59 for (int mask2 = 0; mask2 < (1 << m); mask2++) 60 { 61 dp[i][mask1 ^ mask2] += (dp[i - 1][mask1] * cnt[i - 1][mask2])%MOD; 62 dp[i][mask1 ^ mask2] %= MOD; 63 } 64 return (int)dp[n][(1 << m) - 1]; 65 } 66 };