数位dp,记忆化搜索
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int mod=20123;
int f[120][120],a[120],cnt;
//pos是从最高位cnt搜索到当前位pos,num是从cnt位到pos-1位过程中1或者2的总数
//mlmit表示是否有限制
int dfs(int pos,int num,bool limit){
//递归到终点
if(!pos) return num;
//之前搜索过
if(!limit&&f[pos][num]!=-1) return f[pos][num];
//开始搜索
int len=limit?a[pos]:9;
int ans=0;
for(int i=0;i<=len;++i){
//递归向下搜索
if(i==1||i==2) ans=(ans+dfs(pos-1,num+1,limit&&i==len))%mod;
else ans=(ans+dfs(pos-1,num,limit&&i==len))%mod;
}
//记忆化存储
if(!limit) f[pos][num]=ans;
return ans;
}
int main(){
ios::sync_with_stdio(false);
string s;
while(cin>>s){
memset(f,-1,sizeof(f));
cnt=s.length();
for(int i=0;i<cnt;++i) a[cnt-i]=s[i]-'0';
printf("%d\n",dfs(cnt,0,1));
}
return 0;
}