4080. 第k个数(二分搜索)————acwing杯27场周赛

第k个数

给定一个 n×m 的方格矩阵,每个方格内都有一个整数元素。

其中第 i 行第 j 列的方格中的元素为 i×j(行和列都从 1 开始编号)。

现在,需要你将这 n×m 个整数按照非严格单调递增的顺序一一写出。

请问,你写出的第 k 个整数是多少。

输入格式
一行,三个整数 n,m,k。

输出格式
一行,输出你写出的第 k 个整数。

数据范围
前 6 个测试点满足 1≤n,m≤10。
所有测试点满足 1≤n,m≤5×10^5,1≤k≤n×m。

输入样例1:
2 2 2
输出样例1:
2
输入样例2:
2 3 4
输出样例2:
3
输入样例3:
1 10 5
输出样例3:
5

题解

本题要求写出的第k个整数,假设第k个整数为x,因为矩阵中总会有一些相同的数,整数x的位置是大于等于k个整数的,
因此最后序列整数 x+1 所在的位置一定是大于k个整数的,x-1的位置一定是小于k个整数的,
我们可以用二分查询大于等于k个整数的最左端点,就是x

如何统计某个数x前面有多少个小于等于他的数呢?
因为矩阵是nxm的
每行的数字是用行数乘列数,那么我们要求每行的小于等于x的个数的话
假设行数为 i,k为从1到m的列数, i * k = x,k = x/i 向下取整,求得每行的数累加

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;

/*

*/
LL n,m,k;
bool check(LL mid)//判断mid前面的数是否大于等于k个
{
    LL res = 0;
    for(int i=1; i<=n; ++i){
        res += min(m,mid/i);  //这里注意要和m取最小,不能超过m
    }
    return res >= k;
}
int main()
{
    cin>>n>>m>>k;
    LL l = 1, r = n*m;
    while(l<r){
        LL mid = (l + r) >> 1;
        if(check(mid)) r= mid;
        else l = mid + 1;
        
    }
    cout<<l<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葛济维的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值