C - Unusual Product (CodeForces 405C)

C - Unusual Product (CodeForces 405C)

Little Chris is a huge fan of linear algebra. This time he has been given a homework about the unusual square of a square matrix.

The dot product of two integer number vectors x and y of size n is the sum of the products of the corresponding components of the vectors. The unusual square of an n × n square matrix A is defined as the sum of n dot products. The i-th of them is the dot product of the i-th row vector and the i-th column vector in the matrix A.

Fortunately for Chris, he has to work only in GF(2)! This means that all operations (addition, multiplication) are calculated modulo 2. In fact, the matrix A is binary: each element of A is either 0 or 1. For example, consider the following matrix A:

The unusual square of A is equal to (1·1 + 1·0 + 1·1) + (0·1 + 1·1 + 1·0) + (1·1 + 0·1 + 0·0) = 0 + 1 + 1 = 0.

However, there is much more to the homework. Chris has to process q queries; each query can be one of the following:

  1. given a row index i, flip all the values in the i-th row in A;
  2. given a column index i, flip all the values in the i-th column in A;
  3. find the unusual square of A.

To flip a bit value w means to change it to 1 - w, i.e., 1 changes to 0 and 0 changes to 1.

Given the initial matrix A, output the answers for each query of the third type! Can you solve Chris's homework?

Input

The first line of input contains an integer n (1 ≤ n ≤ 1000), the number of rows and the number of columns in the matrix A. The next n lines describe the matrix: the i-th line contains n space-separated bits and describes the i-th row of A. The j-th number of the i-th line aij (0 ≤ aij ≤ 1) is the element on the intersection of the i-th row and the j-th column of A.

The next line of input contains an integer q (1 ≤ q ≤ 106), the number of queries. Each of the next q lines describes a single query, which can be one of the following:

  • i — flip the values of the i-th row;
  • i — flip the values of the i-th column;
  • 3 — output the unusual square of A.

Note: since the size of the input and output could be very large, don't use slow output techniques in your language. For example, do not use input and output streams (cin, cout) in C++.

Output

Let the number of the 3rd type queries in the input be m. Output a single string sof length m, where the i-th symbol of s is the value of the unusual square of A for the i-th query of the 3rd type as it appears in the input.

Examples

Input

3
1 1 1
0 1 1
1 0 0
12
3
2 3
3
2 2
2 2
1 3
3
3
1 2
2 1
1 1
3

Output

01001

题目翻译:

小克里斯是线性代数的狂热爱好者。这次他的家庭作业是关于一个方阵的不寻常的平方。


大小为n的两个整数向量x和y的点积是向量的对应分量的乘积的和。n×n方矩阵A的奇平方定义为n点积的和。第i个是矩阵A中第i行向量和第i列向量的点积。


幸运的是,Chris只需要在GF(2)中工作!这意味着所有的运算(加法、乘法)都是按模2计算的。事实上,矩阵A是二进制的:A的每个元素不是0就是1。例如,考虑以下矩阵A:

不同寻常的平方等于(1 * 1 + 1·0 + 1 * 1)+ (0 * 1 + 1 * 1 + 1·0)+ (1 * 1 + 0 * 1 + 0·0)= 0 + 1 + 1 = 0。


然而,作业还有很多。Chris必须处理q查询;每个查询都可以是下列查询之一:


给定一个行索引i,翻转a中的第i行中的所有值;

给定一个列索引i,翻转a的第i列中的所有值;

找出不寻常的A的平方。

将一个位值w翻转为1 - w,即。, 1变为0 0变为1。


给定初始矩阵A,输出第三种类型的每个查询的答案!你能解决克里斯的家庭作业吗?


输入

输入的第一行包含一个整数n (1≤n≤1000)的行数和列数矩阵A下n行描述矩阵:i n行包含空格分隔的比特和描述i排的j的第i线aij (0≤aij≤1)是元素的十字路口的第i个行和j列。


下一行输入包含整数q(1≤q≤106),查询个数。下面的每一行q描述一个查询,可以是以下查询之一:


1 i-翻转第i行的值;

2 i-翻转第i列的值;

3 -输出不寻常的正方形A。

注意:由于输入和输出的大小可能非常大,所以在您的语言中不要使用慢速输出技术。例如,不要在c++中使用输入和输出流(cin、cout)。


输出

假设输入中的第3类查询的个数为m。输出一个长度为m的字符串s,其中s的第i个符号是输入中出现的第3类查询的不寻常的a的平方的值。


例子

输入

3

1 1 1

0 1 1

1 0 0

12

3

2 3

3

2 2

2 2

1 3

3

3

1 2

2 1

1

3

输出

01001

思路:

这道题的意思就是让i行和i列上的数相乘之后相加,推倒之后你会发现,只有对角线的数字乘了一次,其余的数字都乘了两次。既然乘了两次,那么只有两种情况,一种是0*1=0+0=0,另 一种是(1*1+1*1)%2=0,这两种模2后都等于0,所以这些都不需要算了……既然是模2,那么直接用异或来算都可以了……当把每行或者每列的每个值都由0变1或者由1变0后,那么主对角线的肯定有一个值变了,所以结果值再异或1就行了。

AC代码:

#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
char a[1000010];
int main()
{
    int n,i,j,k,q,ans=0,cnt=0;
    scanf("%d",&n);
    for(i=0; i<n; i++)
        for(j=0; j<n; j++)
        {
            scanf("%d",&k);
            if(i==j)
                ans^=k;
        }
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d",&k);
        if(k==3)
            a[cnt++]=ans+'0';
        else
        {
            scanf("%d",&k);
            ans^=1;
        }
    }
    a[cnt]=0;
    puts(a);
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值