codeforces D. Multiplication Table 二分答案

傷城~ 2022-07-24 08:19 265阅读 0赞

D. Multiplication Table

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Bizon the Champion isn’t just charming, he also is very smart.

While some of us were learning the multiplication table, Bizon the Champion had fun in his own manner. Bizon the Champion painted an n × m multiplication table, where the element on the intersection of the i-th row and j-th column equals i·j (the rows and columns of the table are numbered starting from 1). Then he was asked: what number in the table is the k-th largest number? Bizon the Champion always answered correctly and immediately. Can you repeat his success?

Consider the given multiplication table. If you write out all n·m numbers from the table in the non-decreasing order, then the k-th number you write out is called the k-th largest number.

Input

The single line contains integers n, m and k (1 ≤ n, m ≤ 5·105; 1 ≤ k ≤ n·m).

Output

Print the k-th largest number in a n × m multiplication table.

Examples

input

  1. 2 2 2

output

  1. 2

input

  1. 2 3 4

output

  1. 3

input

  1. 1 10 5

output

  1. 5

Note

A 2 × 3 multiplication table looks like this:

  1. 1 2 3
  2. 2 4 6

题意: 有一个n*m的table, 第i行j列的数字是i*j, 让你求这个表中第k大的数.

分析: 开始知道使用二分, 然而一直不知道怎么二分. 后来看官方题解才知道..

我们可以二分第k大的数, 然后判断是不是成立, 第k大的数有一个特点, 就是比它小的数一定小于k个, 当比它小的数大于等于k个的时候, 一定不是第k大的数, 有了这个单调性, 我们就可以进行二分了. 二分l=1, r=n*m, mid = l+r>>1;

检查的时候从每一行开始, 求小于mid的数目((x-1)/row), 把这些数目相加,检查是不是小于k;

但是有一点值得注意, 就是我们二分得到的答案是不是一定存在于n*m的表中呢? 比如2*3的表, 5 就不会在表中.

由于我们二分得到的是满足情况的最大值. 如果有一个不在表中, 但是满足比它小的数小于k, 那么他后面一定有一个数满足在表中, 同时满足比它小的数小于k, 再大一些的数就不满足条件了.

  1. #include<bits/stdc++.h>
  2. #define inf 0x3f3f3f3f
  3. using namespace std;
  4. typedef long long ll;
  5. typedef pair<int,int> pii;
  6. const int N=100010,MOD=1e9+7;
  7. ll n,m,k;
  8. ll check(ll x )
  9. {
  10. ll sum=0;
  11. for(int i=1;i<=n;i++){
  12. sum += min(m,(x-1)/i);
  13. }
  14. return sum;
  15. }
  16. int main()
  17. {
  18. cin>>n>>m>>k;
  19. ll l=1,r=n*m,ret;
  20. while(l<=r)
  21. {
  22. ll mid=l+r>>1;
  23. if(check(mid) < k){
  24. l=mid+1;
  25. ret=mid;
  26. }
  27. else r=mid-1;
  28. }
  29. cout<<ret<<endl;
  30. return 0;
  31. }

发表评论

表情:
评论列表 (有 0 条评论,265人围观)

还没有评论,来说两句吧...

相关阅读

    相关 codeforces 159 D(几何二分)

    [传送门][Link 1] 题意:给你n个点,问与x轴相切,并且包含这n个点的圆的最小半径是多少。 思路:真是做的的怀疑人生。思路是首先判断点是否在一边。 如果在一边一定