数位DP入门(A

题目链接:https://cn.vjudge.net/contest/278036#problem/A

具体思路:对于给定的数,我们按照位数进行运算,枚举每一位上可能的数,在枚举的时候需要注意几个条件,第一个,当前位上不能是4,第二如果前一位是6的话,当前的这一位不能是2,然后注意这个条件就可以了。

AC代码:

#include<iostream>
#include<stack>
#include<iomanip>
#include<cmath>
#include<queue>
#include<stdio.h>
#include<map>
#include<string>
#include<cstring>
using namespace std;
# define ll long long
const int maxn = 1e6+100;
int dig[10];
int dp[10];
int dfs(int len,bool fp,bool is6)//fp是用来判断是不是首位上的最大值,is6是用来判断当前的上一位是不是6
{
    if(len==0)
        return 1;
    if(!fp&&dp[len][is6]!=-1)
        return dp[len][is6];
    int ans=0,fmax=fp?dig[len]:9;//如果是首位的话,只能枚举到首位,不是的话,0-9都是可以的。
    for(int i=0; i<=fmax; i++)
    {
        if((i==4)||(is6&&i==2))
            continue;
        ans+=dfs(len-1,fp&&i==fmax,i==6);
    }
    if(!fp)
        dp[len][is6]=ans;
    return ans;
}
int fac(int n)
{
    memset(dp,-1,sizeof(dp));
    int num=0;
    while(n)//把每一位取出来
    {
        dig[++num]=n%10;
        n/=10;
    }
    return dfs(num,1,0);
}
int cal(int n,int m)
{
    return fac(m)-fac(n);
}
int main()
{
    int l,r;
    while(~scanf("%d %d",&l,&r)&&(l+r))
    {
        printf("%d
",cal(l-1,r));
    }
    return 0;
}

B题:

题目链接:https://cn.vjudge.net/contest/278036#problem/B

题目大意:让你求出1-n有多少个49,然后输出来。

具体思路:我们可以先把不满足情况的找出来,然后再总总数去减去这个数就可以了,但是要注意一点,再所有的不满足情况中,0也算是不满足的,但是要求n是大于1的,所以需要最终结果加上1. 

#include<iostream>
#include<cstring>
#include<stack>
#include<stdio.h>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
# define ll long long
const int maxn = 20+5;
ll dig[maxn],dp[maxn][maxn];
ll dfs(ll len,bool fp,bool is4)
{
    if(!len)
        return 1;
    if(!fp&&dp[len][is4]!=-1)
        return dp[len][is4];
    ll ans=0,fmax=fp?dig[len]:9;
    for(int i=0; i<=fmax; i++)
    {
        if(i==9&&is4)
            continue;
        ans+=dfs(len-1,fp&&i==fmax,i==4);//这个地方的fp需要根据两个变量进行比较,上一位和当前的这一位。
    }
    dp[len][is4]=ans;
    return ans;
}
ll cal(ll t)
{
    memset(dp,-1,sizeof(dp));
    int num=0;
    while(t)
    {
        dig[++num]=t%10;
        t/=10;
    }
    return dfs(num,1,0);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n;
        scanf("%lld",&n);
        printf("%lld
",n-cal(n)+1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/letlifestop/p/10262738.html