BZOJ 3679 数字之积 数位DP

旧巷老猫 提交于 2019-11-27 13:37:29

思路:数位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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!