Increasing Numbers (AGC 011 E)

First Post:

Last Update:

Word Count:
628

Read Time:
2 min

Page View: loading...

原题链接

称一个数是递增的,当且仅当它在 进制表示法下的各位数码从高位到低位单调不降;例如, 是递增的,而 不是。

给定一个数 ,问其最少可被表示为几个递增数的和。


我们称一个数是好的,当且仅当其当其在 进制表示法下各位数码均为 ,注意到任何一个递增的数可以被写成不超过 个好数的和;而任意不超过 个好数的和也必定是递增的。

因此,假如 可以被写成不超过 个好数的和,则 可以被写成 个递增数的和。

容易得到,一个 位的好数可以写成

因此 可以被写成不超过 个好数的和时,有

变形后可以得到

表示 进制下的各位数字和,则有

同时注意到,当 满足上式时,可以逆向得到一组不超过 个的好数,使其和为

总之, 可以被表示为不超过 个好数的和的充分必要条件。

又因为条件的成立具有单调性,因此可以进行二分答案。

注意到 时一定可行,因此在区间 上二分即可,这里 表示 十进制下长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <vector>
using namespace std;

static constexpr uint64_t pow10[9] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};

vector<uint64_t> read_bigint(const string &s) {
vector<uint64_t> result;
result.reserve((s.size() + 7) >> 3);
auto it = s.rbegin();
size_t cnt = 0, val = 0;
for (; it != s.rend(); ++it, ++cnt) {
if (cnt == 8)
result.emplace_back(val), cnt = val = 0;
val += (*it - '0') * pow10[cnt];
}
result.emplace_back(val);
return result;
}

vector<uint64_t> add(vector<uint64_t> a, uint32_t b) {
a.empty() ? a.emplace_back(b) : a[0] += b;
uint64_t carry = a[0] / pow10[8];
a[0] %= pow10[8];
for (size_t i = 1; carry; ++i) {
if (i == a.size())
a.emplace_back(0);
a[i] += carry, carry = a[i] / pow10[8], a[i] %= pow10[8];
}
return a;
}

vector<uint64_t> mul(vector<uint64_t> a, uint32_t b) {
if (a.empty())
return a;
uint64_t carry = 0;
for (size_t i = 0; i < a.size() || carry; ++i) {
if (i == a.size())
a.emplace_back(0);
uint64_t cur = (i < a.size() ? a[i] : (uint64_t)0) * b + carry;
a[i] = cur % pow10[8], carry = cur / pow10[8];
}
return a;
}

uint64_t S(const vector<uint64_t> &a) {
uint64_t result = 0;
for (size_t i = 0; i < a.size(); ++i)
for (uint64_t cur = a[i]; cur; cur /= 10)
result += cur % 10;
return result;
}

int main() {
cin.tie(nullptr)->sync_with_stdio(false);
string s;
cin >> s;
auto nums = read_bigint(s);
uint64_t L = 0, R = s.length();
while (L < R) {
uint64_t k = L + ((R - L) >> 1);
S(mul(add(nums, k), 9)) <= 9 * k ? R = k : L = k + 1;
}
cout << L << '\n';
return 0;
}