计蒜客 翻硬币 数学题,

Posted stupid_one

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 翻硬币 数学题,相关的知识,希望对你有一定的参考价值。

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

 

以上是关于计蒜客 翻硬币 数学题,的主要内容,如果未能解决你的问题,请参考以下文章

计蒜客 30990 - An Olympian Math Problem - [简单数学题][2018ICPC南京网络预赛A题]

计蒜客 31452 - Supreme Number - [简单数学][2018ICPC沈阳网络预赛K题]

计蒜客 ACM-ICPC 2018 南京赛区网络预赛 A. An Olympian Math Problem-数学公式题

计蒜客之斐波那契数列

计蒜客课程竞赛入门--蒜头学算数 流程记

计蒜客NOIP2017提高组模拟赛day1