数位dp小技巧
一个奇怪的东西
正反都能dp!:
正常我们数位dp都是从高到低,以这样的方式保证其小于给定数->
ll n;
int num[N],l;
ll dp[];
ll dfs(int p,int lim){
if(p==0) return 1;
if(!lim&&~dp[]) return dp[];
int Uplim=lim?num[p]:9;
ll res=0;
for(int i=0;i<=Uplim;i++) {
res+=dfs(p-1,lim&&(i==Uplim));
}
if(!lim) dp[]=res;
return res;
}
int main(){
scanf("%lld",&n);
while(n) num[++l]=n%10,n/=10;
printf("%lld\n",dfs(l,1));
}
然而从低到高位应该是这样的:
ll n;
int num[N],l;
ll dp[];
ll dfs(int p,int fl){
if(p==l+1) return fl;
if(~dp[]) return dp[];
ll res=0;
for(int i=0;i<10;i++) {
res+=dfs(p+1,i<num[p]||(i==num[p]&&fl));
}
return dp[]=res;
}
int main(){
scanf("%lld",&n);
while(n) num[++l]=n%10,n/=10;
printf("%lld\n",dfs(1,1));
}
这个在某些特殊情况下可以消除一些后效性和麻烦的步骤
注意每次跑不同数的时候要清空dp