codeforces1107D. Compression

题目链接 琪亚娜世界第一可爱

给出矩阵A,构造矩阵B,满足:
i ∈ [ 1 , n ] , j ∈ [ 1 , n ] 且 n m o d    x = 0 , 满 足 A [ i ] [ j ] = B [ ⌈ i x ⌉ ] [ ⌈ j x ⌉ ] i\in [1,n] , j\in [1,n] 且n\mod x =0,满足A[i][j]=B[\lceil\frac{i}{x}\rceil][\lceil \frac{j}{x} \rceil ] i[1,n],j[1,n]nmodx=0,A[i][j]=B[xi][xj]
求最大的x的值


根据题意,将原矩阵分为多个长度为x的子矩阵,每个子矩阵中元素都要一样。暴力求解,从n开始试一直试到2,如果都不行就是1 。
但是这样我们需要每次都把矩阵遍历一遍,所以要进一步优化。
因为这是一个0-1矩阵,矩阵中只有元素0或1,所以我们可以记这个矩阵的前缀和。记perSum[i][j]为矩阵的前缀和数组,表示位于元素aij左上部分中1的个数。
在这里插入图片描述 所以现在判断子矩阵中元素是否都相同,就可以用个数/面积的方法在O(1)的时间内判断出来了


#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>

#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return

#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
const int maxn=5205;

int N;
char store[maxn][maxn];
int preSum[maxn][maxn];
inline int tran(char c);
inline int getSqure(int upX,int upY,int downX,int downY);
int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int num;
    char c;
    cin>>N;
    rep(i,1,N+1){
        rep(j,1,N/4+1){
            cin>>c;
            num=tran(c);
            int pos=j*4,lim=(j-1)*4;
            while(pos>lim){
                store[i][pos]=num%2+'0';
                num=num>>1;
                pos--;
            }
        }
    }

    rep(i,1,N+1)
        preSum[0][i]=0;
    rep(i,1,N+1){
        store[i][0]=0;
        rep(j,1,N+1){
            preSum[i][j]=preSum[i][j-1]+(int)(store[i][j]=='1');
        }
        rep(j,1,N+1)
            preSum[i][j]+=preSum[i-1][j];
    }
    
    int compass=N;
    while(compass>1){
        if(N%compass){
            compass--;
            continue;
        }

        bool safe=true;
        rep(i,1,N/compass+1){
            rep(j,1,N/compass+1){
                int upX=(i-1)*compass,upY=(j-1)*compass;
                int downX=i*compass,downY=j*compass;
                int sum=getSqure(upX,upY,downX,downY);
                int area=(downX-upX)*(downY-upY);
                if(sum%area){
                    safe=false;
                    break;
                }
            }
            if(!safe)
                break;
        }

        if(safe){
            break;
        }
        compass--;
    }
    cout<<compass<<endl;

    re 0;
}
inline int tran(char c){
    if('0'<=c && c<='9')
        re c-'0';
    re c-'A'+10;
}
inline int getSqure(int upX,int upY,int downX,int downY){
    re preSum[downX][downY]-preSum[upX][downY]-preSum[downX][upY]+preSum[upX][upY];
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值