SJTU OJ 1228 Matrix Sum

本文介绍了解决SJTUOJ1228 MatrixSum问题的一种方法,通过将矩阵中的奇数设为1、偶数设为0,统计子矩阵中元素和为奇数的情况。采用逐行合并的方式简化问题,并给出具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SJTU OJ 1228 Matrix Sum

原题链接

这道题做法不唯一,这里只写一个我第一次做时想出来的一个方法。
首先令所有奇数为1,所有偶数为0。假定一个单行的矩阵,比如是00101100011101,数其中和为奇数的子矩阵个数。我们发现连续的0取其中不论几个都不影响奇偶。假设有n个连续的0,那么可以取0~n一共n+1种情况。当矩阵只含有第一个1时,两侧的0的取法有3*2=6种。当矩阵含有前三个1时,有3*4=12种。可以发现规律。
但是子矩阵不一定单行,所以就把位置靠下的行并到上面的某一行(不妨仍然奇数为1偶数为0),然后同上操作这一行。
下面是代码:

#include <iostream>
#include <cstdio>
using namespace std;
long long, re1 = 0, re2 = 0;//re1奇数re2偶数;
int store_zero[405];//存储每一串0的取法;
int work[405];//每次操作的那一行;
int len = 0;//实时为store_zero[]的有效长度;
int arr[405][405] = {0};
void count_it(){
    int now = 0;
    for (int i=0; i<n; i++){
        now++;
        if (work[i] == 1){
            store_zero[len++] = now;
            now = 0;
        }
    }
    if (len == 0) return;//没有1;
    store_zero[len++] = ++now;
    for (int i=0; i<len; i++){
        for (int j=i+1; j<len; j+=2){
            re1 += (store_zero[i] * store_zero[j]);
        }
    }
    len = 0;
    return;
}
int main()
{
    scanf("%d", &n);
    int d;
    for (int i=0; i<n; i++){
        for (int j=0; j<n; j++){
            scanf("%d", &d);
            arr[i][j] = d%2;
        }
    }
    for (int i=0; i<n; i++){//从第几行开始;
        for (int j=0; j<n; j++){//先把这一行赋给work[];
            work[j] = arr[i][j];
        }
        count_it();
        for (int j=i+1; j<n; j++){//再把下面的行依次加到work[];
            for (int k=0; k<n; k++){
                work[k] = (work[k]+arr[j][k])%2;
            }
            count_it();
        }
        for (int j=0; j<n; j++){//work[]清零;
            work[j] = 0;
        }
    }
    re2 = n*n*(n+1)*(n+1)/4 - re1;//子矩阵总数n*n*(n+1)*(n+1)/4;
    cout << re1 << ' ' << re2;
    return 0;
}

还有复杂度更低的算法,欢迎指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值