关于矩阵初始值我们可以用互质数对进行筛选,复杂度大致为N*M.
初始完值后,用二维单调队列维护矩阵最大值即可。
代码如下
#include <bits/stdc++.h>
using namespace std;
#define MAXN 5050
#define ll long long
int n,m,k;
int a[MAXN][MAXN];
int mx[MAXN][MAXN];
#define fore(l,r) for(int i=(l);i<=r;i++)
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(!a[i][j])
{
int G=i*j/__gcd(i,j);
int X=i;
int Y=j;
int k=1;
while(X<=n&&Y<=m)
{
a[X][Y]=k*G;k++;
X+=i;
Y+=j;
}
}
}
deque<int>p;
for(int i=1;i<=n;i++)
{
while(!p.empty())p.pop_back();
for(int j=1;j<=m;j++)
{
while (!p.empty() && j - p.back() >= k)p.pop_back();
while (!p.empty() && a[i][j] >= a[i][p.front()])p.pop_front();
if(!p.empty()&&a[i][j]>a[i][p.back()])p.push_back(j);
else p.push_front(j);
mx[i][j]= p.back();
}
}
ll ans=0;
for(int j=k;j<=m;j++)
{
while(!p.empty())p.pop_front();
for(int i=1;i<=n;i++)
{
int x=a[i][mx[i][j]];
while(!p.empty()&&i-p.back()>=k)p.pop_back();
while(!p.empty()&&x>=a[p.front()][mx[p.front()][j]])p.pop_front();
if(!p.empty()&&x>a[p.back()][mx[p.back()][j]])p.push_back(i);
else p.push_front(i);
if(i>=k)ans+=a[p.back()][mx[p.back()][j]];
}
}
cout<<ans<<endl;
}