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

逆向思维,二分查找答案。


对于一个n*m乘法表,要查数字n前有多少小于等于n的,可用

ll solve(ll t){

    ll res=0;
    for(int i=1;i<=n;i++){
            ll tmp=t/i;
            if(tmp>m)
                tmp=m;
            res+=tmp;
    }
    return res;
}

二分时若solve(n)<k则肯定不是想要的n,使l=mid+1,但若solve(n)==k时可能是想要的n,也可能不是(n不一定属于乘法表),所以应令r=mid

代码:

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
long long n,m,k;
ll solve(ll t){
    ll res=0;
    for(int i=1;i<=n;i++){
            ll tmp=t/i;
            if(tmp>m)
                tmp=m;
            res+=tmp;
    }
    return res;
}

int main(){
    while(~scanf("%I64d%I64d%I64d",&n,&m,&k)){

            ll l=1;
            ll r=n*m+1;
            ll mid;
            while(l<r){
                    mid=(l+r)/2;
                    if(solve(mid)<k)
                       l=mid+1;
                    else
                        r=mid;

            }
            mid=(l+r)/2;
          
            printf("%I64d\n",mid);
    }
    return 0;
}


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