Codeforces Round #256 (Div. 2) D Multiplication Table(很巧妙二分)

Codeforces Round #256 (Div. 2) D Multiplication Table

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.
Sample test(s)
Input

2 2 2

Output

2

Input

2 3 4

Output

3

Input

1 10 5

Output

5

Note

A 2 × 3 multiplication table looks like this:

1 2 3
2 4 6

传送门
这题 有两点出乎我意料,第一没想到可以用二分,第二没想到这里的二分还有点小变形,直接二分会错误。
这题 想法是 在一个不递减 的序列里二分 一个中间值后 用这个值 找每行比他小的数的个数 加起来 看满足题意否。
就是有一个特殊的是 当 那个值满足的 个数 大于 你要求第几个的时候,先不要将右端点减一,因为你这里右端点 存的不是位置 是哪个位置的数值 而且 相邻两个数字有相等的情况,所以就不能忙的减一。

#include <stdio.h>
int a, b;
long long c;
int main(){
    scanf("%d%d%lld", &a, &b, &c);
    long long s = 1, e = (long long)a * b,ans=0;
    int i, j;
    for(;s<e;)
    {
        long long m = (s + e) / 2;
        long long cc = 0;
        j = b;
        for(i = 1; i <= a; i++){
            while((long long)i*j>m) j--;
            cc+= j;
        }
        if(cc<c)
        {
            s=m+1;//表示要求的一定比这个数大一
        }
        else
            e=m;//注意由于这题的特殊性,比如第一组数据2 2 2 时 1 2 2 4排列时 第二个和第三个都是2,不能立马e=m-1; 
    }
    printf("%lld\n",e);
    return 0;
}

你可能感兴趣的:(二分)