和49那题是一样的,就是判断的时候会多一两个判断,然后就是要注意每次算出来的结果都是在小于n的情况下成立的。
#include <stdio.h>
#include <string.h>
#define ll __int64
ll dp[25][3];
ll solve(ll n)
{
ll i,j,k;
j=n;
int top=0;
ll que[25];
memset(que,0,sizeof(que));
while(j)
{
que[++top]=j%10;
j/=10;
}
k=0;
int flag=0;
// for(i=1;i<=top;i++) printf("**%d",que[i]);printf("\n");
//int que[25];
// memset(que,0,sizeof(que));
for(i=top;i>=1;i--)
{
k+=dp[i-1][2]*que[i];
if(flag) k+=dp[i-1][0]*que[i];
else
{
if(que[i]>6) k+=dp[i-1][1];
if(que[i]>4) k+=dp[i-1][0];
if(que[i+1]==6&&que[i]>2) k+=dp[i][1];
}
if(que[i+1]==6&&que[i]==2||que[i]==4) flag=1;
}
return k;
}
int main()
{
ll n,m;
memset(dp,0,sizeof(dp));
dp[0][0]=1; //这里注意初始化
for(int i=1;i<=20;i++)
{
dp[i][0]=dp[i-1][0]*9-dp[i-1][1];
dp[i][1]=dp[i-1][0];
dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];
}
while(scanf("%I64d%I64d",&n,&m)!=EOF&&n+m)
{
ll ans,tmp;
ans=solve(n);
tmp=solve(m+1); //注意这里放的是m
// printf("**%I64d %I64d\n",ans,tmp);
printf("%I64d\n",m-n+1-tmp+ans);
}
return 0;
}
**********************************************
用DFS写的,,,其实看过很多dfs的DP,然后平生最恨这样写!!。。。。。但是自己写了之后其实感觉还不错。。。。。
state表示之前是否有6,fp大概表示是否达到了原值的那个数字。
#include <stdio.h>
#include <string.h>
#define ll __int64
ll que[30];
ll dp[30][2];
ll dfs(int len,int state,int fp)
{
if(!len) return 1;
if(dp[len][state]!=-1&&!fp) return dp[len][state];
int i,j,k;
ll ret=0;
int fmax=fp?que[len]:9;
for(i=0;i<=fmax;i++)
{
if(i==4||i==2&&state) continue;
ret+=dfs(len-1,i==6,fp&&i==fmax);
}
if(!fp) dp[len][state]=ret;
return ret;
}
ll solve(ll n)
{
ll i,j,k;
j=n;
k=0;
while(j)
{
que[++k]=j%10;
j/=10;
}
return dfs(k,0,1);
}
int main()
{
ll n,m;
memset(dp,-1,sizeof(dp));
while(scanf("%I64d%I64d",&n,&m)!=EOF&&n+m)
{
ll a,b;
a=solve(n-1);
b=solve(m);
printf("%I64d\n",b-a);
}
return 0;
}