51nod1425 减减数

14 篇文章 0 订阅

题目

Solution

借用一下讨论区的方法
假设ans = f(n),首先f是满足单调不下降的。最优的策略即为每次减去数值最大的那一位。
对于一个数n,设他一共有x位,那么 n % 1 0 x − 1 n\%10^{x-1} n%10x1,即后x-1位将共享总x位的最大值。
那么最大的那一位会影响它以及后面的所有位,比如119221这种情况
但是可能不一定会每次都刚好把每一位都减到0,有可能减多,需要进行补回后x-1位上多减去的值。
于是这道题变成了按位削减每次分成"?0000…"和“0???..”这样的两半部分去搜索即可。

首先,想要最优,我们必须每次都取各位数字中的最大值进行操作
其次,操作次数是单调的: f ( n ) > = f ( n − 1 ) f(n)>=f(n−1) f(n)>=f(n1)
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)9910log(前面的乘积)
两个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);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值