JZOJ 1389. 玩詐欺的小杉
阿新 • • 發佈:2020-08-10
思路
考慮一個點要不要翻,如果它左邊的點為 \(1\),那麼它必須翻
所以我們可以從左往右一列一列地翻
先列舉第 \(0\) 列的狀態
然後之後的列就確定了
判斷一下最後一列是不是 \(0\) 就行了
狀壓快速翻
\(Code\)
#include<cstdio> #include<cstring> using namespace std; int n , m , t , b[21] , c[21]; int main() { scanf("%d%d%d" , &n , &m , &t); char s[50]; for(; t; t--) { memset(c , 0 , sizeof c); for(register int i = 1; i <= n; i++) { scanf("%s" , s); for(register int j = 0; j < m; j++) c[j + 1] = (c[j + 1] << 1) + s[j] - '0'; } int up = (1 << n) - 1 , ans = 0; for(register int i = 0; i <= up; i++) { b[0] = i; for(register int j = 1; j <= m; j++) b[j] = c[j] & up; for(register int j = 1; j <= m; j++) { b[j] = b[j] ^ b[j - 1] ^ (b[j - 1] << 1) ^ (b[j - 1] << 2) ^ (b[j - 1] >> 1) ^ (b[j - 1] >> 2); b[j] &= up; b[j + 1] = (b[j + 1] ^ b[j - 1]) & up; } if (b[m] == 0) ans++; } printf("%d\n" , ans); } }