CodeForce-817C 思维题 二分

传送门:题目

题意:

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

题解:

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

题目中给的n的范围是 1018 10 18 ,肯定不能暴力,所以我们需要找到规律,我们假设:
当前有一个数,满足条件: numdigit(num) n u m − d i g i t ( n u m ) ≥ s
那么num+1是不是也满足条件呢? (num+1)digit(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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值