CodeForce-817C 思维题 二分

传送门:题目

题意:

给两个数,一个数n,一个数s,找到[1,n]中,满足等式: n u m d i g i t ( n u m ) s的个数。digit()函数是一个数的各个数位的累加和。

题解:

主要是怎么思考这个数学模型。

题目中给的n的范围是 10 18 ,肯定不能暴力,所以我们需要找到规律,我们假设:
当前有一个数,满足条件: n u m d i g i t ( n u m ) s
那么num+1是不是也满足条件呢? ( n u m + 1 ) d i g i t ( n u m + 1 ) s ?
我们发现减号的前面加1,如果这个数的个位小于9,那么减号的后面也加一,值不变,依然满足条件,那么如果这个数的个位数等于9,那么减号后面的同样加上一个数,等式依然成立。

得到结论:该函数是单调递增函数(平增平增平增~~~~)

所以我们二分出,第一个满足条件的点,那么它后面的就都满足了。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;

long long n, s;
bool solve(long long x) {
    int digit = 0;
    long long xx = x;
    while (x) {
        digit += x % 10;
        x /= 10;
    }
    return xx - digit >= s;
}
int main(void) {
    cin >> n >> s;
    long long l = 1, r = n,mid = (l + r) / 2,ans = -1;
    while (l <= r) {
        debug(mid);
        if (solve(mid) == false)
            l = mid + 1;
        else {
            ans = mid;
            r = mid - 1;
        }
        mid = (l + r) / 2;
    }
    if (ans == -1)
        cout << 0 << endl;
    else
        cout << n - ans + 1 << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/shadandeajian/article/details/81590365
今日推荐