【思维题】CodeForce 817C Really Big Numbers

这段时间要沉迷刷题一段时间了,就让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;
}

如果有问题,欢迎大家指正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值