BZOJ 3679 数字之积 数位DP

思路:数位DP

提交:\(2\)

错因:进行下一层\(dfs\)时的状态转移出错

题解:

还是记忆化搜索就行,但是要用\(map\)记忆化。
见代码

#include<cstdio>
#include<iostream>
#include<map>
#define R register int
#define ll long long
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0;
	register I f=1; register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} ll n,l,r,num[19],len,stk[19],top;
map<ll,ll> f[20];
inline void print() {
	for(R i=1;i<=top;++i) cout<<stk[i];
}
inline ll dfs(int l,bool ul,bool ck,ll ml) {
	if(l==0) {return ml<=n&&ml>0?1:0;}
	if(!ul&&!ck&&f[l].count(ml)) return f[l][ml];
	R mx=ul?num[l]:9; register ll cnt=0;  
	for(R i=0;i<=mx;++i)  
		if(ck&&i==0) stk[++top]=i,cnt+=dfs(l-1,ul&&i==mx,true,0),--top;//一直是前导零 
		else if(ck&&i!=0) stk[++top]=i,cnt+=dfs(l-1,ul&&i==mx,false,i),--top;//第一次不是前导零 
		else if(!ck&&i!=0) stk[++top]=i,cnt+=dfs(l-1,ul&&i==mx,false,ml*i),--top;//之前有不是前导零的时刻
		//注意到i=0且不是前导零时就不必向下dfs了 
	return f[l][ml]=cnt;
}
inline ll solve(ll x) { len=0; 
	for(R i=1;i<=19;++i) f[i].clear();
	while(x) num[++len]=x%10,x/=10;
	return dfs(len,1,1,0);
}
inline void main() {g(n),g(l),g(r); printf("%lld\n",solve(r-1)-solve(l-1));}
} signed main() {Luitaryi::main(); return 0;}

2019.08.16
84

posted @ 2019-08-16 19:38  LuitaryiJack  阅读(231)  评论(0编辑  收藏  举报