不要62(数位DP)
第一个数位 d p dp dp题,发现去年用打表前缀和过的。。
思路1:记忆化搜索,具体看代码吧。
#include<bits/stdc++.h>
using namespace std;
const int N=12;
int dp[N][2],digit[N]; //digit[i]保存第i位的数字(从1开始) 1是最低位.
int dfs(int len,int pre,int sta,int ismax){ //dp[i][0]表示i位数且前一位不是6的答案
int ans=0,maxx; //len当前位数长度,pre当前位的前一位,前一位是否为6,该位是否原数
//dp[i][1]表示i位数且前1位是6的答案.
if(!len) return 1;//递归到最深处 0位数直接返回.
if(!ismax&&~dp[len][sta]) return dp[len][sta];//记忆化.
maxx=ismax?digit[len]:9;
for(int i=0;i<=maxx;i++){
if(i==4||(pre==6&&i==2)) continue;
ans+=dfs(len-1,i,i==6,ismax&&i==maxx);
}
if(!ismax) dp[len][sta]=ans;
return ans;
}
int solve(int n){
int len=0;
while(n){
digit[++len]=n%10;
n/=10;
}
return dfs(len,-1,0,1);
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m)){
memset(dp,-1,sizeof dp);
printf("%d\n",solve(m)-solve(n-1));
}
}
思路2 : d p dp dp。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
int dp[N][10],n,m,d[N];
void init(int n){
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
if(j!=4&&!(j==6&&k==2))
dp[i][j]+=dp[i-1][k];
}
int solve(int n){
int len=0,ans=0;
while(n){
d[++len]=n%10,n/=10;
}
d[len+1]=0;
for(int i=len;i>=1;i--){
for(int j=0;j<d[i];j++)
if(!(d[i+1]==6&&j==2)) //这一句判断不能省略,4可以省略因为在init已经判断过了.
ans+=dp[i][j];
if(d[i]==4||(d[i+1]==6&&d[i]==2)) break;
}
return ans;
}
int main(){
init(7);
while(~scanf("%d%d",&n,&m)&&(n||m)){
printf("%d\n",solve(m+1)-solve(n));//注意这里solve(x)是计算[0,x-1]的满足条件的个数.
}
return 0;
}