题解:先预处理2*max(n,m)的矩阵前缀然后暴力枚举k = 2~max(n,m)的情况求出来需要变更的最小值用矩阵相减求出小每一个小矩阵中的最小值即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mx = 5e3+5;
char s[mx][mx];
int a[2][mx][mx];
int main(){
memset(a,0,sizeof(a));
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
scanf("%s",s[i]+1);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
a[s[i][j]-'0'][i][j]++;
int d = 2*max(n,m);
for(int i = 1; i <= d; i++)
for(int j = 1; j <= d; j++){
a[0][i][j]+=a[0][i][j-1];
a[1][i][j]+=a[1][i][j-1];
if(i>n||j>m)
a[0][i][j]++;
}
for(int i = 1; i <= d; i++)
for(int j = 1; j <= d; j++){
a[0][i][j]+=a[0][i-1][j];
a[1][i][j]+=a[1][i-1][j];
}
// for(int i = 1; i <= d; i++)
// for(int j = 1; j <= d; j++)
// printf("%d%c",a[0][i][j],j==d?'\n':' ');
d/=2;
int ans = d*d;
for(int i = 2; i <= d; i++){
int sum = 0;
for(int j = i; j <= d+i; j+=i)
for(int k = i; k <= d+i; k+=i){
int num_one = a[1][j][k]+a[1][j-i][k-i]-a[1][j-i][k]-a[1][j][k-i];
int num_zero = a[0][j][k]+a[0][j-i][k-i]-a[0][j-i][k]-a[0][j][k-i];
sum += min(num_one,num_zero);
}
ans = min(ans,sum);
}
printf("%d\n",ans);
return 0;
}