从低位往高位考虑。设当前个位为 \(k\),暴力搜索这一位向上进 \(i\) 位,设 \(\left\lfloor\frac{n}{10}\right\rfloor - i\) 的答案为 \(t\)。
- 若 \(t > 10i + k\) 显然就不可行,因为就算个位全部填 \(1\) 也不能补齐;
- 否则 \(n\) 的答案就是 \(\max(t, \left\lceil\frac{10i+k}{3}\right\rceil)\),取 \(\max\) 是因为有可能之前不够个位至少需要数的个数,要补。
直观感觉是 \(i\) 不会很大(事实上 \(i \le 1\)),所以这个做法跑得很快。
code
// Problem: C - 1, 2, 3 - Decomposition
// Contest: AtCoder - AtCoder Regular Contest 123
// URL: https://atcoder.jp/contests/arc123/tasks/arc123_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
ll dfs(ll n) {
if (n < 10) {
return (n + 2) / 3;
}
ll k = n % 10;
for (int i = 0;; ++i) {
if (!k && !i) {
continue;
}
ll t = dfs(n / 10 - i);
if (t <= k + 10 * i) {
return max(t, (k + 10 * i + 2) / 3);
}
}
}
void solve() {
ll n;
scanf("%lld", &n);
printf("%lld\n", dfs(n));
}
int main() {
int T = 1;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
- Decomposition AtCoder Regular Contest 123decomposition atcoder regular contest atcoder regular contest 165 minimization atcoder regular contest atcoder regular contest 166 atcoder regular contest degree atcoder regular contest sliding atcoder regular contest 167 atcoder regular contest 164 atcoder regular contest builder subsegments atcoder regular contest