1. 程式人生 > >洛谷P3857 [TJOI2008]彩燈(線性基)

洛谷P3857 [TJOI2008]彩燈(線性基)

兩個 -- include tchar 輸出 long long 線性基 open 告訴

題目描述

Peter女朋友的生日快到了,他親自設計了一組彩燈,想給女朋友一個驚喜。已知一組彩燈是由一排N個獨立的燈泡構成的,並且有M個開關控制它們。從數學的角度看,這一排彩燈的任何一個彩燈只有亮與不亮兩個狀態,所以共有2N個樣式。由於技術上的問題,Peter設計的每個開關控制的彩燈沒有什麽規律,當一個開關被按下的時候,它會把所有它控制的彩燈改變狀態(即亮變成不亮,不亮變成亮)。假如告訴你他設計的每個開關所控制的彩燈範圍,你能否幫他計算出這些彩燈有多少種樣式可以展示給他的女朋友?

註: 開始時所有彩燈都是不亮的狀態。

輸入輸出格式

輸入格式:

每組測試數據第一行為兩個整數N和M,用空格隔開。緊接著是有M行,每行都是一個長度為N的字符串,表示一個開關控制彩燈的範圍(N盞燈),如果第i個字母是大寫字母’O’,則表示這個開關控制第i盞燈,如果第i個字母是大寫字母’X’,則表示這個開關不控制此燈。

輸出格式:

輸出這些開關和彩燈可以變換出來的樣式數目。由於這個值可能會很大,請求出它對於整數2008的余數。

輸入輸出樣例

輸入樣例#1: 復制
2 3
OO
XO
OX
輸出樣例#1: 復制
4

說明

可見樣例中第一個開關控制了所有的彩燈,而後兩個開關分別控制了第一個和第二個彩燈,這樣我們可以只用後兩個開關控制彩燈,可以變換出來所有的22個狀態。

30%的數據中,N和M不超過15。

70%的數據中,N和M不超過50。

要是不知道這題是線性基的話可能要想很久,。。

但是知道了線性基這題就比較zz了,就是求個最大線性無關組,直接輸出pow(2,線性基的大小)

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long 
using namespace std;
const int MAXN = 1e5 + 10,  B = 62, mod = 2008;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < 0 || c > 9) {if
(c == -) f = -1; c = getchar();} while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * f; } int N, M; char s[MAXN]; LL P[MAXN]; void Insert(LL x) { for(int i = B; i >= 0; i--) { if((x >> i) & 1) { if(!P[i]) {P[i] = x; return ;} x = x ^ P[i]; } } } main() { #ifdef WIN32 freopen("a.in", "r", stdin); #endif scanf("%d %d", &N, &M); for(int i = 1; i <= M; i++) { scanf("%s", s + 1); LL now = 0; for(int j = 1; j <= N; j++) if(s[j] == X) now = now | (1ll << j - 1); // printf("%d\n", now); Insert(now); } int num = 0; for(int i = 0; i <= B; i++) if(P[i]) num++; printf("%lld", (1ll << num) % mod ); }

洛谷P3857 [TJOI2008]彩燈(線性基)