【貪心】【P2117】小Z的矩陣
阿新 • • 發佈:2018-08-05
put 正整數 通過 new template null 輸出 org scrip
傳送門
Description
小Z最近迷上了矩陣,他定義了一個對於一種特殊矩陣的特征函數G。對於N*N的矩陣A,A的所有元素均為0或1,
當然詢問一個矩陣的G值實在是太簡單了。小Z在給出一個N*N矩陣的同時將給你Q個操作,操作描述如下:
操作1:形如一個整數1和一個整數x,表示將第x行的元素全部“翻轉”。
操作2:形如一個整數2和一個整數x,表示將第x列的元素全部“翻轉”。
操作3:形如一個整數3,表示詢問當前矩陣的特征值G。
“翻轉”的定義為將1變成0,將0變成1。
Input
第1行:兩個正整數N,Q。 N表示矩陣的行數(列數),Q表示詢問的個數。
接下來N行:一個N*N的矩陣A,0<=A[i][j]<=1。
接下來Q行:Q個操作。
Output
一行若幹個數,中間沒有空格,分別表示每個操作的結果(操作1和操作2不需要輸出)。
Sample Input
3 12 1 1 1 0 1 1 1 0 0 3 2 3 3 2 2 2 2 1 3 3 3 1 2 2 1 1 1 3
Sample Output
01001
Hint
30% N<=100, Q<=10^5
100% N<=1,000, Q <=5*10^5
Solution
對於30%,O(NQ)暴力出奇跡
對於100%,我們考慮這樣一個事實:對於所有的i!=j,會計算四次A,其中通過(i,j)計算A[i][j]*A[j][i],,通過(j,i)計算A[j][i]*A[i][j]。不難發現,無論A[i][j]*A[j][i]等於0還是等於1,相加後取模2恒等於零。
數學證明如下:對於ans=Σ(A[i][j]*A[j][i]+A[i][j]*A[j][i])(i<j) Mod 2=Σ2(A[i][j]*A[j][i]) Mod 2=2*Σ(A[i][j]*A[j][i]) Mod 2=0
所以對於i!=j矩陣元素對答案沒有貢獻。
所以ans=ΣA[i][i] Mod 2。每次修改 ans^=1即可。
Code
#include<cstdio> #define ci const int inline void qr(int &x) { char ch=getchar(),lst=NULL;while(ch>‘9‘||ch<‘0‘) lst=ch,ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if (lst==‘-‘) x=-x; } char buf[20]; inline void write(int x,const char aft,const bool pt) { if(x<0) {putchar(‘-‘);x=-x;} int top=0; do { buf[++top]=x%10+‘0‘; x/=10; } while(x); while(top) putchar(buf[top--]); if(pt) putchar(aft); } template <typename T> inline T mmax(const T &a,const T &b) {if(a>b) return a;return b;} template <typename T> inline T mmin(const T &a,const T &b) {if(a<b) return a;return b;} template <typename T> inline T mabs(const T &a) {if(a<0) return -a;return a;} template <typename T> inline void mswap(T &a,T &b) {T temp=a;a=b;b=temp;} int n,m,a; bool ans; int main() { qr(n);qr(m); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(i!=j) qr(a);else {a=0;qr(a);if(a) ans^=1;} while(m--) {a=0;qr(a);if(a==3) {if(ans) putchar(‘1‘);else putchar(‘0‘);}else {qr(a);ans^=1;}} putchar(‘\n‘); return 0; }
Summary
對於計算了兩遍然後答案Mod 2的元素,可以直接pass。
真tm神仙
【貪心】【P2117】小Z的矩陣