Educational Codeforces Round 48 (Rated for Div. 2) D - Vasya And The Matrix (位运算构造)

原题地址:http://codeforces.com/contest/1016/problem/D

题意:给你一个矩阵的长宽分别为 n,m n , m .然后将每一行的元素全部异或起来,得到序列 a,a[i] a , a [ i ] 表示将第i行的数字全部异或起来的值.然后再将每一列的元素全部异或起来,得到序列 b b .现在问你能否构造出这么一个矩阵满足题意,如果能,请输出这个矩阵.

思路:位运算的骚操作太多了.我们可以假设我们构造的矩阵除了第一行和第一列其余元素全为0.那么显然要满足题意,除了 (1,1) ( 1 , 1 ) 这个格子的元素,其余元素就是 a,b a , b 序列的值.那么如何求 (1,1) ( 1 , 1 ) 这个位置的元素呢?
从大佬的代码中,发现了这么一个规律,对于异或运算,假设 ab=c a ⨁ b = c ,那么 b=ac b = a ⨁ c .
所以我们只需要将第一行的元素(除了第1个)全部异或起来,在和 a[1] a [ 1 ] 去异或就得到了 (1,1) ( 1 , 1 ) 的值.
然后我们只需要将这个元素和第1列的元素异或起来,去验证是否和 b[1] b [ 1 ] 相等就行了.

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 5;
int n, m;
ll a[105], b[105];
ll mp[105][105];
int main() {
    scanf("%d%d", &n, &m);

    for(int i = 1; i <= n; i++) {
        scanf("%I64d", &a[i]);
        mp[i][1] = a[i];
    }
    for(int i = 1; i <= m; i++) {
        scanf("%I64d", &b[i]);
        mp[1][i] = b[i];
    }
    ll x = 0;
    for(int i = 2; i <= m; i++) x ^= b[i];
    ll sum = a[1] ^ x;//求(1,1)
    mp[1][1] = sum;
    for(int i = 2; i <= n; i++) {
        sum ^= a[i];
    }
    if(sum != b[1]) printf("NO\n");//验证是否相等
    else {
        printf("YES\n");
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                printf("%I64d ", mp[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(Educational Codeforces Round 48 (Rated for Div. 2) D - Vasya And The Matrix (位运算构造))