思路:这题本来是要卡一手log,但数据水了,除去求gcd,就二维单调队列裸题
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <string.h>
#include <map>
#include <iostream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> pii;
const int maxn = 5e3 + 100;
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
int que[maxn * 100];
int a[maxn][maxn];
int g[maxn][maxn];
int main(int argc, char const *argv[])
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i++){
int le = 1, ri = 0;
for(int j = 1; j < k; j++){
g[i][j] = i * j / gcd(i, j);
while(le <= ri && g[i][j] >= g[i][que[ri]]) ri--;
que[++ri] = j;
}
for(int j = k; j <= m; j++){
g[i][j] = i * j / gcd(i, j);
while(le <= ri && g[i][j] >= g[i][que[ri]]) ri--;
que[++ri] = j;
a[i][j - k + 1] = g[i][que[le]];
while(j - que[le] + 1 >= k && le <= ri) {
le++;
}
}
}
for(int j = 1; j <= m - k + 1; j++){
int le = 1, ri = 0;
for(int i = 1; i < k; i++){
while(le <= ri && a[i][j] >= a[que[ri]][j]) ri--;
que[++ri] = i;
}
for(int i = k; i <= n; i++){
while(le <= ri && a[i][j] >= a[que[ri]][j]) ri--;
que[++ri] = i;
a[i - k + 1][j] = a[que[le]][j];
while(i - que[le] + 1 >= k && le <= ri) le++;
}
}
LL ans = 0;
for(int i = 1; i <= n - k + 1; i++){
for(int j = 1; j <= m - k + 1; j++){
ans += a[i][j];
}
}
printf("%lld
", ans);
return 0;
}