Educational Codeforces Round 59 (Rated for Div. 2) D Compression 【dp】

题目链接:http://codeforces.com/contest/1107/problem/D

这道题只要把主要问题找出来就有思路了。

题目的矩阵是 n*n的,要想压缩成 n/x *n/x 的矩阵需要满足一个条件,假设x == 2,那么这个矩阵将会被分成4小块矩阵,如果这四个小矩阵每一块要么全是1要么全是0,那这个矩阵就能压缩成n/2 *n/2的矩阵。

因为题目给的n比较大,如果暴力求小矩阵是否全是1或者0肯定会超时的。

我用的方法是dp求出每一个 左上角为0*0,右下角为i*j 这个矩阵的和,当我们需要某一块小矩阵的时候,能直接取出dp[i][j] 并且除去不需要的部分就能很快的知道某个小矩阵的和。

只要主要问题能找出来,上面的dp应该也能想得到,其次还有一个难点就是输入的快慢。

起初的方法是用一个字符串存16个二进制数,然后一个一个的放入矩阵里面,但是这种方法非常慢。

换成二进制位移判断1或0的方法赋值能快非常多。

#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int Maxn = 6e3+10;

int dp[Maxn][Maxn], n;
char G[Maxn][Maxn];

void init() {
    for(int i = 0; i < n; ++i)
        if(G[i][0] == '1') dp[i][0] = 1;

    for(int i = 0; i < n; ++i) {
        for(int j = 1; j < n; ++j) {
            dp[i][j] += dp[i][j-1];
            if(G[i][j] == '1') dp[i][j]++;
        }
    }
    for(int j = 0; j < n; ++j) {
        for(int i = 1; i < n; ++i) {
            dp[i][j] += dp[i-1][j];
        }
    }
}

void solve() {
    int ans = 1;
    for(int i = 2; i <= n; ++i) {
        bool ok = true;
        if(n % i != 0) continue;
        for(int ii = i-1; ii <= n; ii += i) {
            for(int jj = i-1; jj <= n; jj += i) {
                int tmp = dp[ii][jj];
                if(ii-i >= 0 && jj-i >= 0) tmp += dp[ii-i][jj-i];
                if(ii-i >= 0) tmp -= dp[ii-i][jj];
                if(jj-i >= 0) tmp -= dp[ii][jj-i];
                if(tmp == 0 || tmp == i*i) continue;
                else {
                    ok = false; break;
                }
            }
            if(!ok) break;
        }
        if(ok) ans = i;
    }
    printf("%d\n", ans);
}

int main(void)
{
    char str[Maxn];
	scanf("%d", &n);
	for(int i = 0; i < n; ++i) {
        scanf("%s", str);
        for(int j = 0; j < (n>>2); ++j) {
            int num = str[j] <= '9' ? str[j]-'0' : str[j]-'A'+10;
            int fir = j*4;
            for(int k = 0; k < 4; ++k) {
                if((num>>k) & 1) G[i][fir+3-k] = '1';
                else G[i][fir+3-k] = '0';
            }
            G[i][fir+4] = '\0';
        }
	}
	memset(dp, 0, sizeof(dp));
	init();
	solve();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值