数位DP HDU 2089

杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。 
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。 
不吉利的数字为所有含有4或62的号码。例如: 
62315 73418 88914 
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。 
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。 

Input

输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。 

Output

对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。 

Sample Input

1 100
0 0

Sample Output

80
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b)  for(int i=a;i<=b;i++)
int dp[21][2];//dp[i][j]表示第i位数字是否为6的符合条件的数目
int p[20];//用来存放各位数
typedef long long ll;
int dfs(int pos,int pre,int sta,bool limit)//pos表示当前位数,pre表前一位是多少,sta表是否
{//前一位是6,limit表是否达到上限,也就是当前位数所能达到的最大值
    if(pos==-1)
        return 1;
    if(!limit&&dp[pos][sta]!=-1)//减小复杂度,不用重复计算
        return dp[pos][sta];
    int up=limit?p[pos]:9;
    int ans=0;
    rep(i,0,up)
    {
            if(i==4||(i==2&&pre==6))continue;
        ans+=dfs(pos-1,i,i==6,limit && i==p[pos]);
    }
    if(!limit)
        dp[pos][sta]=ans;
    return ans;
}
ll solve(int a)
{
    int tot=0;
    while(a)
    {
        p[tot++]=a%10;
        a/=10;
    }
    return dfs(tot-1,-1,0,true);
}
int main()
{
    ll n_,m_;
    while(cin>>n_>>m_&&(n_||m_)){
    memset(dp,-1,sizeof(dp));
    ll ans1=solve(n_-1);//这里注意是n_-1,如果是直接相减就会多减去,使区间变小,可以举[1,10]
    ll ans2=solve(m_);
    cout<<ans2-ans1<<endl;
    }
 return 0;
}

下面是WA的代码有没有知道为啥,大牛们帮忙look一下,谢谢

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1000000;
int dp[11][11];
#define rep(i,a,b)  for(int i=a;i<=b;i++)
void getdp()
{
   dp[0][0]=1;
    rep(i,1,9)
    {
        rep(j,0,9)
        {
            if(j==4)
              dp[i][j]=0;
            else if(j==6)
            {
                rep(k,0,9)
                dp[i][j]+=dp[i-1][k];
                dp[i][j]-=dp[i-1][2];
            }
            else
                rep(k,0,9)
                dp[i][j]+=dp[i-1][k];
        }
    }

}
ll solve(int a)
{
    int f[10]={0};
    int tot=0;
    while(a)
    {
        f[++tot]=a%10;
        a/=10;
    }
    ll ans=0;
   for(int i=tot;i>=1;i--)
    {
        rep(j,0,f[i]-1)
        if((f[i+1]!=6&&j!=2)||j!=4)
            ans+=dp[i][j];
        if((f[i+1]==6&&f[i]==2)||f[i]==4)
            break;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    getdp();
    rep(i,1,9)
    {
        rep(j,0,9)
        cout<<dp[i][j]<<" ";
        cout<<endl;
    }
    int n;
    int m;
    while(cin>>n>>m&&(n||m))
    {
    //cout<<solve(m+1);
    cout<<solve(m+1)-solve(n)<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/81456270
今日推荐