数位dp:在数位上做动态规划
Bomb
求含49的数字个数(49连号)。
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<queue> #include<cmath> using namespace std; #define inf 0x3f3f3f3f typedef long long ll; //找0-n含49的数字个数(49看作一个整体) ll dp[50][2];//不含49的数字的个数 //[数位] 当数为i时,有多少个数不含49 int digit[20];//2^63-1//19位 ll dfs(int len,bool if4,bool limit)//执行的是数位dp(dfs+记忆化搜索) { if(len==0) return 1; if(limit==0&&dp[len][if4])//并且当前的数位已经统计过 return dp[len][if4]; ll sum=0,up; if(limit==1) up=digit[len]; else up=9; for(int i=0;i<=up;i++) { if(if4&&i==9)//不要49 continue; //没有49所有数的数量 sum+=dfs(len-1,i==4,limit&&i==up); } if(!limit)//是一个完整的状态,等到下一次dfs的时候可以直接返回 dp[len][if4]=sum; return sum; } ll solve(ll x) { int num=0;//有多少个数位 while(x) { digit[++num]=x%10; x/=10; } dfs(num,0,1);//从高位,从上面往下面遍历 } int main() { int t; cin>>t; while(t--) { ll n; cin>>n; cout<<n+1-solve(n)<<endl;//+1因为算上0再减去不含49的 // 给了上下界cout<<solve(m)-solve(n-1)<<endl; } return 0; }
不要62
HDU - 2089给出a、b两个区间,求所有不含有4或62(62连号)的数字的个数。
AC代码:

1 #include<string.h> 2 #include<iostream> 3 #include<stdio.h> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<map> 8 #include<cmath> 9 using namespace std; 10 #define inf 0x3f3f3f3f 11 const int N=50; 12 typedef long long ll; 13 14 int digit[25]; 15 ll dp[N][2]; 16 17 ll dfs(int len,bool if6,bool limit) 18 { 19 if(len==0) 20 return 1; 21 if(limit==0&&dp[len][if6]) 22 return dp[len][if6]; 23 ll cnt=0,up; 24 if(limit==1) 25 up=digit[len]; 26 else 27 up=9; 28 for(int i=0; i<=up; i++) 29 { 30 if(if6&&i==2)//不要62 31 continue; 32 if(i==4)//不要4 33 continue; 34 cnt+=dfs(len-1,i==6,limit&&i==up); 35 } 36 if(limit==0) 37 dp[len][if6]=cnt; 38 return cnt; 39 } 40 41 ll solve(ll x) 42 { 43 int num=0; 44 while(x) 45 { 46 digit[++num]=x%10; 47 x/=10; 48 } 49 return dfs(num,0,1); 50 } 51 52 int main() 53 { 54 ll n,m; 55 while(cin>>n>>m) 56 { 57 if(n==0&&m==0) 58 break; 59 memset(dp,0,sizeof(dp)); 60 cout<<solve(m)-solve(n-1)<<endl; 61 } 62 return 0; 63 }