n個燈,每一個燈只有開關兩種狀態,開始都關着。ios
m個開關,每一個開關對應若干個燈,拉動一下就會使該開關控制的全部燈改變狀態。spa
問有多少種不一樣的狀態。code
考慮把每一個燈抽象成一個二進制位,開是1,關是0,那麼當前狀態就是一個二進制數。ci
而後拉動開關就至關於給當前狀態異或上一個數。get
因而問題轉化爲求一些數能xor出多少不一樣的數。(由於一開始是0,異或0等於不異或)io
考慮創建一個線性基。既然原序列xor能獲得的集合與線性基xor能獲得的集合相同,那麼其大小也是相同的。class
因爲線性基異或獲得的數一定沒有重複的(根據基的定義,有且僅有一種方式獲得一個數),那麼選或不選線性基裏的一個數就會致使獲得不一樣的數。stream
而每一個數有選和不選兩種狀態,因此答案是\(2^{size}\)(\(size\)是線性基內元素個數,即線性基大小)二進制
注意溢出。集合
#include <iostream> using namespace std; char read() { char c; do { c = getchar(); } while (c == ' ' || c == '\n' || c == '\r'); return c; } typedef long long type; const int W = 51; type basis[W + 1]; int siz; void ins(type x) { for (int i = W; i >= 1; i--) { if (x >> (i - 1)) { if (basis[i] == 0) { basis[i] = x; siz++; return; } x ^= basis[i]; } } } int w, n; int main() { cin >> w >> n; for (int i = 1; i <= n; i++) { type x = 0; for (int j = 1; j <= w; j++) { char c; c = read(); if (c == 'O') x += 1ll << (j - 1); } ins(x); } cout << (1ll << siz) % 2008 << endl; }