数位dp

不要62

方法一:记忆化搜索

/*
数位dp分析
1.把每位数字抠出来
2.分情况:画树状分析图
3.预处理数组
4.注意处理最后一种情况
5.注意位数的问题,预处理的数组表示的含义弄清
*/

#include 

using namespace std;
const int N = 12;
typedef long long ll;
const int mod = 1e9+7;
int dp[10][2];
int digit[20];
int dfs(int pos,bool state,int fp)//state为1代表上一位是6,fp为1代表是否为顶部
{
    if(!pos)return 1;
    if(!fp&&dp[pos][state]!=-1)return dp[pos][state];
    int i,fpmax,ret = 0;
    fpmax=fp?digit[pos]:9;
    for(int i=0;i<=fpmax;i++)
    {
        if(i==4||state&&i==2)continue;
        ret+=dfs(pos-1,i==6,fp&&i==fpmax);
    }
    if(!fp)dp[pos][state]=ret;
    return ret;
}
int cal(int n)
{
    int len=0;
    while(n)digit[++len]=n%10,n/=10;//len要从第一位开始,因为len为0时直接返回1
    return dfs(len,0,1);
}

int main()
{
    int l,r;
    while(cin>>l>>r&&l&&r)
    {
        memset(dp,-1,sizeof(dp));
        cout<<cal(r)-cal(l-1)<<endl;
    }




    return 0;
}

法二:预处理dp

/*
数位dp分析
1.把每位数字抠出来
2.分情况:画树状分析图
3.预处理数组
4.注意处理最后一种情况
5.注意位数的问题,预处理的数组表示的含义弄清
*/

#include 
using namespace std;
const int N = 12;
typedef long long ll;
int f[N][100];
int k,b,l,r;
void init()//以j为头,i位数的数字范围内有多少个数
{
    for(int i=0;i<=9;i++)if(i!=4)f[1][i]=1;
    for(int i=2;i<=10;i++)
    {
        for(int j=0;j<=9;j++)
        {
            for(int k=0;k<=9;k++)
            {
                if(k==4||j==4)continue;
                if(j==6&&k==2)continue;
                f[i][j] += f[i-1][k];
            }
        }
    }
}
int dp(int n)
{
    if(!n) return 1;
    int last = 0 ,res = 0;
    vector<int>nums;
    while(n)
    {
        nums.push_back(n%10);
        n/=10;
    }

    for(int i=nums.size()-1;i>=0;i--)
    {
        int x = nums[i];
        if(last == 4)break;

        for(int j=0;j<=x-1;j++)
        {
            if(last==6&&j==2)continue;
            
            res+=f[i+1][j];
        }
        //cout<
        if(last == 6&&x==2)break;
        if(!i&&x!=4&&!(last==6&&x==2))res++;
        last = x;

    }
    return res;
}
int main()
{
    init();
    while(cin>>l>>r&&l&&r)
    {


       cout<<dp(r)-dp(l-1)<<endl;
       //for(int i=0;i<=9;i++)
       // cout<<" "<
    }
    return 0;
}

你可能感兴趣的:(acm,动态规划,算法,dfs)