Gym 101484 I Matrix Sum

题意:题目给了一个矩阵 A 的定义:
Aij=Nk=1(Mik+Mkj)Mij
其中 M 是一个仅由 0 和 1 组成的矩阵
问,给定一个 nn(1n1e3) A 矩阵, 问满足上面等式的 M 矩阵有几个

分析: 这个题的关键就是从 A 矩阵中找出几个与 M 矩阵的等式关系。
我们用 RAi 表示 A 矩阵第 i 行的和, RMi 表示 M
CAi 表示 A 矩阵第 i 列的和, CMi 表示 M
totA 表示 A 矩阵的总和,totM 表示 M 矩阵的总和

则原定义变成了: Aij=RMi+CMjMij

1. 可以发现的是,每个 Mij 是使 A i j 列上的位置都+1,这样的话,每个 M 上的 1,都会在 A 上加 2n1 次。因此可以得到第一个等式:
totM(2n1)=totA
所以,如果 totA 不整除 2n1 ,答案为 0

2.对于每个 RAi 可以发现的是,整个 M 上的 1 都会在第 RAi 行上加 1 而且 M i 行的 1 会加 n 次,由等式1 我们可以得到 totM=totA/(2n1)
所以会得到第二个等式: RAi=totM+(n1)RMi
所以,如果 RAitotM 不整除 n1 ,答案也是 0 .
对于每个CAi 也同理。由此,我们可以得到每个 RMi CMi

3. 如果上面两个都满足,那么我们回到题目给的等式, RMi , CMi Aij 都是已知了,所以这样每个 Mij 都能求出来,而且是唯一的。求出来之后判断一下是否为 0 1,是的话答案就是 1 ,不是答案就是0.

4. 还有一个特殊情况就是 n=1 的时候,直接特判一下即可。

以下是代码。

#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const int MAXN = 1005;
const int MAXM = 100005;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const double FINF = 1000000000000000.0;
const ll MOD = 1000000007;
const double PI = acos(-1);

int f[MAXN][MAXN];

int row[MAXN], col[MAXN];

int main() {
    memset(col, 0, sizeof(col));
    memset(row, 0, sizeof(row));
    int n, tot = 0; scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            scanf("%d", &f[i][j]);
            row[i] += f[i][j];
            col[j] += f[i][j];
            tot += f[i][j];
        }
    }
    if (n == 1) {
        if (f[1][1] == 1 || f[1][1] == 0)goto ans_1;
        else goto ans_0;
    }
    if (tot % (2 * n - 1) != 0)goto ans_0;
    tot = tot / (2 * n - 1);
    for (int i = 1; i <= n; ++i) {
        if ((row[i] - tot) % (n - 1) || row[i] < tot)goto ans_0;
        if ((col[i] - tot) % (n - 1) || col[i] < tot)goto ans_0;
        row[i] = (row[i] - tot) / (n - 1);
        col[i] = (col[i] - tot) / (n - 1);
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            int now = row[i] + col[j] - f[i][j];
            if (now != 0 && now != 1)goto ans_0;
        }
    }
    goto ans_1;
ans_0:
    printf("0\n");
    return 0;
ans_1:
    printf("1\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值