题目链接 琪亚娜世界第一可爱
给出矩阵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];
}