题目描述
Given a matrix of size n\times mn×m and an integer {k}k, where A_{i,j} = lcm(i, j)A
i,j
=lcm(i,j), the least common multiple of {i}i and {j}j. You should determine the sum of the maximums among all k\times kk×k submatrices.
输入描述:
Only one line containing three integers n,m,k~(1\leq n,m \leq 5000, 1 \leq k \leq \min{n, m})n,m,k (1≤n,m≤5000,1≤k≤min{n,m}).
输出描述:
Only one line containing one integer, denoting the answer.
示例1
输入
3 4 2
输出
38
说明
The given matrix is:
1 2 3 4
2 2 6 4
3 6 3 12
The maximums among all 2\times 22×2 submatrices are {2, 6, 6, 6, 6, 12}2,6,6,6,6,12 respectively, and their sum is {38}38.
题目大意:给出三个参数n,m,k,构成元素为lcm(i,j)的n×m矩阵,求所有k×k子矩阵最大值之和。
做法:用一个长度为 k 的单调队列维护最大值,保持队列为单调递减。
压入数值之前,先将所有比之小的数值弹出(如果本身是最小且队列已满,则将队首元素弹出),然后压入数值,这样保证队首元素是该区间最大元素。
代码:
#include<bits/stdc++.h>
using namespace std;
int lcm(int a,int b) //最小公倍数
{
int ta = a,tb = b;
int t = a%b;
while(t){
a = b;
b = t;
t = a%b;
}
return ta*tb/b;
}
deque<int> dq;
int mat[5005][5005];
int a[5005][5005];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
mat[i][j] = lcm(i,j);
for(int i = 1; i <= n; i++){
dq.clear();
dq.push_back(0);//为了程序正常运行
for(int j = 1; j <= m; j++){
if(j-dq.front() >= k) dq.pop_front();//如果队列满
while(!dq.empty() && mat[i][j] >= mat[i][dq.back()])//先将比它小的元素弹出
dq.pop_back();
dq.push_back(j);
a[i][j] = mat[i][dq.front()];
}
}
long long ans = 0;
for(int j = k; j <= m; j++){
dq.clear();
dq.push_back(0);
for(int i = 1; i <= n; i++){
if(i-dq.front() >= k)dq.pop_front();
while(!dq.empty() && a[i][j] >= a[dq.back()][j])
dq.pop_back();
dq.push_back(i);
if(i >= k)ans += a[dq.front()][j];
}
}
cout << ans;
return 0;
}