首页 > 代码库 > 计蒜客 翻硬币 数学题,

计蒜客 翻硬币 数学题,

https://nanti.jisuanke.com/t/14897

描述:

L用硬币玩游戏。他在n*m的矩阵中的每个小格中放一枚硬币,他想将所有的硬币都变成正面向上,但是,他给自己增加一些难度,他只能将整行或者整列的硬币都翻面。当然,他一点也不想做无用功,所以,他想知道当前的状态是否能通过一系列操作后使得所有硬币正面朝上。

 

输入:

首先是一个T,代表数据的组数;每组数据的第一行给出一个n和m,代表行数和列数;接下来n行,每行由m个数(0或者1),0表示硬币正面朝上,1表示硬币反面朝上;

 

数据范围:

n>=1

m>=1

n*m<=1e6

 

输出:

如果能使得所有硬币正面朝上,输出YES;

否则输出NO;

样例输入

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

样例输出

YES
NO

 

看了题解之后我觉得很犀利,我一开始也是学题解这样想的,枚举第一行是否翻转,然后比如001100翻转后,就变成了110011

这样第1、2、5、6列就必须翻转,然后继续这样处理下去。但是觉得很麻烦,因为如果一开始是000000,那么你第一行不翻转,然后呢?然后唯有用第二行来判断了,我想到这样就没想下去了。等会睡觉想。

我的做法是一个以前学到的技巧。不过也只是复习后才想起来了,脑子记不住。

我设row[i]表示第一行是否翻转,col[j]表示第j列是否翻转,是的话就是1,不翻转就是0

那么我需要所有的(a[i][j] + row[i] + col[j]) % 2 == 0恒成立。

也就是a[i][j] + row[i] + col[j] + 2 * k == 0(k 是任意数)

那么由于第i行和第j列的操作是独立的,那么设i = 1,则有a[1][j] + row[1] + col[j] + 2 * k = 0

得到col[j] = -a[1][j] - row[1] - 2*k ①

然后带进去原来的式子,得到a[i][j] + row[i] - a[1][j] - row[1] - 2*k + 2*k = 0

得到row[i] = a[1][j] + row[1] - a[i][j],同理可以设j = 1,得到row[i] = a[1][1] + row[1] - a[i][1] ②

用①②带入原来的式子,有:

a[i][j] + a[1][1] - a[i][1] - a[1][j] = 0要成立。

a[i][j] + a[1][1] - a[i][1] - a[1][j]这个数值就是满足

a[i][j] + row[i] + col[j] + 2 * k = 0的那个数值

也就是(a[i][j] + row[i] + col[j]) % 2 = 0,那么这个数字是奇数的话明显不行。

技术分享
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e6 + 20;
vector<int>vc[maxn];
void work() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        vc[i].clear();
        vc[i].push_back(inf);
        for (int j = 1; j <= m; ++j) {
            int x;
            cin >> x;
            vc[i].push_back(x);
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if ((vc[i][j] - vc[1][j] - vc[i][1] + vc[1][1] + 2) % 2 != 0) {
//                cout << i << " " << j << endl;
                cout << "NO" << endl;
                return;
            }
        }
    }
    cout << "YES" << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    IOS;
    int t;
    cin >> t;
    while (t--) work();
    return 0;
}
View Code

 

计蒜客 翻硬币 数学题,