不要62
方法一:记忆化搜索
/*
数位dp分析
1.把每位数字抠出来
2.分情况:画树状分析图
3.预处理数组
4.注意处理最后一种情况
5.注意位数的问题,预处理的数组表示的含义弄清
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 12;
typedef long long ll;
const int mod = 1e9+7;
int dp[10][2];
int digit[20];
int dfs(int pos,bool state,int fp)//state为1代表上一位是6,fp为1代表是否为顶部
{
if(!pos)return 1;
if(!fp&&dp[pos][state]!=-1)return dp[pos][state];
int i,fpmax,ret = 0;
fpmax=fp?digit[pos]:9;
for(int i=0;i<=fpmax;i++)
{
if(i==4||state&&i==2)continue;
ret+=dfs(pos-1,i==6,fp&&i==fpmax);
}
if(!fp)dp[pos][state]=ret;
return ret;
}
int cal(int n)
{
int len=0;
while(n)digit[++len]=n%10,n/=10;//len要从第一位开始,因为len为0时直接返回1
return dfs(len,0,1);
}
int main()
{
int l,r;
while(cin>>l>>r&&l&&r)
{
memset(dp,-1,sizeof(dp));
cout<<cal(r)-cal(l-1)<<endl;
}
return 0;
}
法二:预处理dp
/*
数位dp分析
1.把每位数字抠出来
2.分情况:画树状分析图
3.预处理数组
4.注意处理最后一种情况
5.注意位数的问题,预处理的数组表示的含义弄清
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 12;
typedef long long ll;
int f[N][100];
int k,b,l,r;
void init()//以j为头,i位数的数字范围内有多少个数
{
for(int i=0;i<=9;i++)if(i!=4)f[1][i]=1;
for(int i=2;i<=10;i++)
{
for(int j=0;j<=9;j++)
{
for(int k=0;k<=9;k++)
{
if(k==4||j==4)continue;
if(j==6&&k==2)continue;
f[i][j] += f[i-1][k];
}
}
}
}
int dp(int n)
{
if(!n) return 1;
int last = 0 ,res = 0;
vector<int>nums;
while(n)
{
nums.push_back(n%10);
n/=10;
}
for(int i=nums.size()-1;i>=0;i--)
{
int x = nums[i];
if(last == 4)break;
for(int j=0;j<=x-1;j++)
{
if(last==6&&j==2)continue;
res+=f[i+1][j];
}
//cout<<res<<endl;
if(last == 6&&x==2)break;
if(!i&&x!=4&&!(last==6&&x==2))res++;
last = x;
}
return res;
}
int main()
{
init();
while(cin>>l>>r&&l&&r)
{
cout<<dp(r)-dp(l-1)<<endl;
//for(int i=0;i<=9;i++)
// cout<<" "<<f[3][0]<<endl;
}
return 0;
}