Solution
借用一下讨论区的方法
假设ans = f(n),首先f是满足单调不下降的。最优的策略即为每次减去数值最大的那一位。
对于一个数n,设他一共有x位,那么
n
%
1
0
x
−
1
n\%10^{x-1}
n%10x−1,即后x-1位将共享总x位的最大值。
那么最大的那一位会影响它以及后面的所有位,比如119221这种情况
但是可能不一定会每次都刚好把每一位都减到0,有可能减多,需要进行补回后x-1位上多减去的值。
于是这道题变成了按位削减每次分成"?0000…"和“0???..”这样的两半部分去搜索即可。
首先,想要最优,我们必须每次都取各位数字中的最大值进行操作
其次,操作次数是单调的:
f
(
n
)
>
=
f
(
n
−
1
)
f(n)>=f(n−1)
f(n)>=f(n−1)
d
f
s
(
n
,
m
x
)
dfs(n,mx)
dfs(n,mx) 要把
n
n
n化为
0
0
0 ,
m
x
mx
mx 表示比数
n
n
n最高位还要高的位的最大值
f
i
r
s
t
first
first表示操作次数,
s
e
c
o
n
d
second
second 表示在将该部分变为
0
0
0的过程中,多余的部分(退位)
时间复杂度可以算,但我懒得算,大致作个估计
m-a.S肯定是x9999…999x形式(也有可能是x000000吧,暂且不管)
对于非x9999…999x形式,dfs(n-m,max(p,mx)),dfs(m-a.S,mx)两部分递归,前者是可以忽略不计的,每次必少一层
那所有复杂度都在x9999…999x上了,大约
l
o
g
(
n
)
∗
9
∗
9
∗
10
∗
l
o
g
(
前面的乘积
)
log(n)*9*9*10*log(前面的乘积)
log(n)∗9∗9∗10∗log(前面的乘积)
两个9代表两个未确定的位,10代表mx范围,log是map复杂度,总之就是
1000
l
o
g
2
n
1000log^2n
1000log2n
Code
#include<bits/stdc++.h>
using namespace std;
#define F first
#define S second
typedef long long ll;
typedef pair<ll,int> pl;
ll n;
map<pl,pl>mp;
pl dfs(ll n,int mx){
if (mp[pl(n,mx)].F) return mp[pl(n,mx)];
if (n<10) return pl(n || mx,max((ll)mx,n)-n);
ll m=1;
while (m<=n/10) m*=10;
int p=n/m;
m*=p;
pl a=dfs(n-m,max(p,mx)),b=dfs(m-a.S,mx);
return mp[pl(n,mx)]=pl(a.F+b.F,b.S);
}
int main(){
scanf("%lld",&n);
printf("%lld",dfs(n,0).F);
}