Codeforces_405C_Unusual Product(思考题)

来源:互联网 发布:手机道路测量软件 编辑:程序博客网 时间:2024/04/28 02:44

题型:数论


题意:

n*n的矩阵,元素是0或1。

定义一种运算:ans = ∑(Aij*Aji),且都是模2运算。

现有三种指令:

(1)1 row:把第row行的的每个元素都反转

(2)2 column:把第column列的每个元素都反转

(3)3:输出运算的解


分析:
不用多说,指令数多达10^6,每次都傻傻的暴力一定呵呵。

由于是模2运算,则有如下特性:

对于加法‘+’:1+1=0

                     0+0=0

                     1+0=0

                     0+1=0

对于乘法‘*’: 1*1=1

                     1*0=0

                     0*1=0

                     0*0=0


尝试分析一下3*3的矩阵:

A11 A12 A13             A11*A11+A12*A21+A13*A31

A21 A22 A23    =    + A12*A21+A22*A22+A32*A23          =     A11*A11+A22*A22+A33*A33+0

A31  A32 A33          + A13*A31+A23*A32+A33*A33


对于每次的反转指令,都等价于修改了主对角线上的一个元素,也就是说在上面推出的式子中,要么多了一个1,要么少了一个1,再考虑一下‘+’的性质,可知每次翻转指令都会将运算结果翻转。

至此,问题解决~


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int n,m;int a[1005][1005];int s[1005];int add(int a,int b){    if(a+b==1) return 1;    else return 0;}int main(){    while(~scanf("%d",&n)){        for(int i=0;i<n;i++){            for(int j=0;j<n;j++){                scanf("%d",&a[i][j]);            }        }        for(int i=0;i<n;i++){            s[i] = 0;            for(int j=0;j<n;j++){                s[i] = add(s[i],(a[i][j]&a[j][i]));            }        }        int ans = 0;        for(int i=0;i<n;i++){            ans = add(ans,s[i]);        }        scanf("%d",&m);        int id,num;        while(m--){            scanf("%d",&id);            if(id==3) printf("%d",ans);            else{                scanf("%d",&num);                if(ans==0) ans=1;                else ans=0;            }        }        puts("");    }    return 0;}


0 0