题目链接:hdu 2089
给两个整数n,m求n到m之间符合给定条件的数
条件:6后面不能是2,不能有4
数位dp裸题,开一个三维数组,dp【i】【j】【k】表示当前为第i位后面符合条件的数量,
j=0:前一位不为6,j=1:前一位是6
k=0:本位取值没有限制,可以从0~9,k-1则是本位的值不能超过原数此位的值。
这样把状态定义好之后就能进行dp了
#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define sqr(a) (a)*(a)
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
int a[20];
int dp[20][2][2];
int pin(int pos,int sta,int lim)
{
if(pos==-1) return 1;
int up=lim?a[pos]:9;
//printf("up=%d\n",up);
if(dp[pos][sta][lim]!=-1) return dp[pos][sta][lim];
int ans=0;
for(int i=0;i<=up;i++)
{
if(i==2&&sta==1)
continue;
if(i==4)
continue;
if(i==up)
{
int tem=lim?1:0;
if(i==6)
ans+=pin(pos-1,1,tem);
else
ans+=pin(pos-1,0,tem);
}
else if(i==6)
ans+=pin(pos-1,1,0);
else
ans+=pin(pos-1,0,0);
}
// printf("%d %d %d=%d\n",pos,sta,lim,ans);
return dp[pos][sta][lim]=ans;
}
int sov(int n)
{
lan(a,0);
lan(dp,-1);
int p=0;
while(n)
{
a[p++]=n%10;
n/=10;
}
p--;
return pin(p,0,1);
}
int main()
{
int n,m;
//printf("%d\n",sov(100));
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
printf("%d\n",sov(m)-sov(n-1));
}
return 0;
}