CodeForces

题目连接:

https://vjudge.net/problem/1753263/origin

其实这道题跟行列式里的分块发有点类似,但也是类似罢了。

主要的思想是每一行,每一列的第一行(或者最后一行)空出,让后根据下列算式:

行异或和:suma = a[1]^a[2]^a[3]...^a[n].

列异或和:sumb = b[1]^b[2]^b[3]...^b[m].

且本题的判断为YES的充要条件是:suma = sumb

有异或和的算法:x^a = b  <==> x^b = a 知:

a[1]^a[2]^a[3] ... ^a[n-1] = a[n]^suma

b[1]^b[2]^b[3] ... ^b[m-1] = = b[m]^sumb

                            |

                            |

------------------------| ---x

比如这两条线的交点为x 则要找到一个x(a[n] = b[m])使他满足:

x^a[1]^a[2]^a[3]^ ... ^a[n-1] = b[m]  且

x^b[1]^b[2]^b[3]^ ... ^ b[m-1] = a[n]

也就是 x^suma^a[n] = b[m], 

故 x = suma^a[n]^b[m].

AC代码以及步骤解释如下:

#include <iostream>
#include <cstdio>
#include <string.h>

using namespace std;
const int MX = 100+10;
int a[MX], b[MX];
int mp[MX][MX];

int main()
{
    memset(mp, 0, sizeof(mp)); //初始化填充0
    int n, m;
    int suma = 0, sumb = 0;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]); //行的异或和
        suma ^= a[i]; //suma是行的总异或和
    }
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d", &b[i]); //列的异或和
        sumb ^= b[i]; //sumb是列的总异或和
    }
    if(suma != sumb) //若行的总异或和不等于列的总异或和,则不成立
    {
        printf("NO
");
        return 0;
    }
    int x = suma^a[n]^b[m]; //根据公式得到x
    for(int i = 1; i <= n; ++i) mp[i][m] = a[i]; //最后行,列进行初始化
    for(int i = 1; i <= m; ++i) mp[n][i] = b[i];
    mp[n][m] = x; //赋值X
    printf("YES
");
    for(int i = 1; i <= n; ++i) //打印矩阵
    {
        for(int j = 1; j <= m; ++j)
            printf("%d ", mp[i][j]);
        printf("
");
    }

}
View Code

如有疑问,欢迎评论提出!

化繁为简 大巧不工
原文地址:https://www.cnblogs.com/mpeter/p/10289355.html