这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
题目意思很简单,就是给定两个数n和s,求解不超过n的Really Big Numbers的个数,Really Big Number的定义是,n - n的各位之和 ≥ s.
二、题目思路以及AC代码
题目其实不难,数论部分也并不难,自己很容易就可以找到规律,只需求解最小的满足要求的数即可,因为n - n的各位之和是随着n的增大而增大的。然后利用二分求解找到最小的满足要求的数即可。
但这里有一点我需要提醒一下,因为这是我一开始犯的错误。当我找到递增的这个规律之后并不满足,还想找一些更加简便的方法。当时我也以为我确实找到了。大致意思如下:
假设一个数写成各位的形式:nxnx-1…n1
那么该数的各位之和就是:nx+nx-1+…+n1
原数的值为:10x-1nx+10x-2nx-1+…+n1
两者做差得:(10x-1-1)nx+(10x-2-1)nx-1…9n2
这样我考虑只要找到一个最小的nx…n2,使得这个成立,然后也就找到最小值了,而我的做法是如果数大于9999…9,则直接让数除以9999…9,但后来发现,这虽然可以找到最小值,但是却无法映射到十进制数,因为这个不连续。举个例子,比如90这个数,它小于99,大于9,所以我可以让n2这个位等于10,但n2=10是无法映射到对应的十进制的,因为十进制的各个位最大是9。因此我最后还是屈服了,直接选择二分法做了。
下面是AC代码:
#include <iostream>
#include <cmath>
using namespace std;
long long a[20];
long long n, s;
bool check(long long m) {
long long sum = 0;
long long tmp = m;
int size = 1;
while (m) {
a[size++] = m % 10;
m /= 10;
}
for (int i = 1; i < size; i++) {
sum += a[i];
}
if (tmp - sum >= s) return true;
return false;
}
int main()
{
cin >> n >> s;
long long l = 1;
long long r = n;
long long ans = n + 1;
while (l < r) {
long long mid = (l + r) / 2;
if (check(mid)) r = mid - 1;
else l = mid + 1;
}
if (check(l)) ans = l;
else ans = l + 1;
cout << n - ans + 1 << endl;
return 0;
}
如果有问题,欢迎大家指正!!!