数位dp( tzoj6061:Bomb-求49个数;tzoj1427: 不要62)
6061:http://www.tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=6061
dfs记忆化搜索
#include<bits/stdc++.h> using namespace std; #define ll long long ll digit[20]; ll dp[20][2]; ll dfs(int len,bool if4,bool limit)//当前数是否是4 是否达到上界 { if(len==0)return 1;//搜索到最低位 最低位一定满足条件 返回1 if(!limit&&dp[len][if4])return dp[len][if4];//未到达上界 并且这个状态已经有答案 ll cnt=0,up_bound=(limit?digit[len]:9); //是不是上界//n=512-> up=5 for(ll i=0;i<=up_bound;i++){ if(if4&&i==9)continue;//剪掉49这一支 cnt+=dfs(len-1,i==4,limit&&i==up_bound); //加上剩余满足条件的 } if(!limit)dp[len][if4]=cnt; //不是上界;记录答案; 是上界的话答案就不能利用之前的了 要另外算 return cnt; } ll solve (ll num) { ll k=0;//记录几个数位 while(num){ digit[++k]=num%10; num/=10; } return dfs(k,false,true); } int main() { ll t; ll n; cin>>t; while(t--){ cin>>n; cout<<n-solve(n)+1<<endl;//总的减去 不包含49的(其中包括了0 所以多减了一个,要加回去) } return 0; }
1427:http://www.tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=1427
和上一题一样;就是49改成62;再加一个4的条件即可
#include <bits/stdc++.h> using namespace std; #define ll long long ll digit[20]; ll dp[20][2]; ll dfs(int len,bool if6,bool limit) { if(len==0)return 1; if(!limit&&dp[len][if6])return dp[len][if6]; ll cnt=0,up_bound=(limit?digit[len]:9); for(ll i=0;i<=up_bound;i++){ if(if6&&i==2)continue; if(i==4)continue; cnt+=dfs(len-1,i==6,limit&&i==up_bound); } if(!limit)dp[len][if6]=cnt; return cnt; } ll solve (ll num) { ll k=0;//记录几个数位 while(num){ digit[++k]=num%10; num/=10; } return dfs(k,false,true); } int main() { ll n,m; while(scanf("%I64d%I64d",&n,&m),n!=0||m!=0){ printf("%I64d\n",solve(m)-solve(n-1)); } return 0; }