题意
给出 n , m , k n,m,k n,m,k,定义 F ( i , j ) = i × j F(i,j)=i\times j F(i,j)=i×j,求出第 k k k 的 F ( i , j ) F(i,j) F(i,j),其中 1 ≤ i ≤ n , 1 ≤ j ≤ m 1\leq i \leq n,1\leq j \leq m 1≤i≤n,1≤j≤m,数据范围: 1 ≤ n , m , k ≤ 1 0 6 1\leq n,m,k \leq 10^6 1≤n,m,k≤106 且 k ≤ n × m k\leq n\times m k≤n×m。
分析
大致画出
F
(
i
,
j
)
F(i,j)
F(i,j) 的分布,可以发现,
F
(
n
,
m
)
F(n,m)
F(n,m) 为最大值,然后由此向下和向右值会减少。因此,考虑从点
(
n
,
m
)
(n,m)
(n,m) 推出其它点,将所有点放入优先队列,每次取最大,并推出下面和右面的两个点,取
k
k
k 次即可。但会出现位置重复的问题,如果使用 map
标记,会超时。观察后可以发现,可以从
(
n
,
m
)
(n,m)
(n,m) 所在的列向右递推,每次只向右推一个数,就可以保证补偿费。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct node
{
ll w;
int x,y;
bool operator < (const node b)const{
return w<b.w;
}
};
priority_queue<node>que;
int main(){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
que.push(node{1LL*i*m,i,m});
ll ans=0;
while(k--){
node t=que.top();
ans=t.w;
que.pop();
if(t.y>1)
que.push(node{1LL*t.x*(t.y-1),t.x,t.y-1});
}
printf("%lld\n",ans);
return 0;
}