hdu5787(数位dp)

基础的数位dp,才发现今天才终于彻底搞懂了数位dp。。。

//
//  main.cpp
//  hdu5787.1
//
//  Created by New_Life on 16/8/10.
//  Copyright © 2016年 chenhuan001. All rights reserved.
//

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;

long long dp[20][5][10010];
int k;
int mod;

long long dfs(int wei[],int p,int flag,long long pre,int pk)
{
    if(p<0) return 1;
    if(flag  == 0  && dp[p][pk][pre]!= -1) return dp[p][pk][pre];
    int mark[10];
    int twei[6];
    memset(mark,0,sizeof(mark));
    memset(twei,0,sizeof(twei));
    long long tp = pre;
    int cnt = 0;
    while(tp)
    {
        twei[ cnt++ ] = tp%10;
        tp/=10;
    }
    for(int i=0;i<pk;i++) mark[twei[i]]++;
    
    if(flag == 1)
    {
        long long sum = 0;
        for(int i=0;i<wei[p];i++)
        {
            if(pk==0 && i==0)
            {
                sum += dfs(wei,p-1,0,0,0);
            }
            else
            {
                if(mark[i]==0)
                    sum += dfs(wei,p-1,0,(pre*10+i)%mod,min(pk+1,k-1));
            }
        }
        if(mark[wei[p]]==0) sum += dfs(wei,p-1,1,(pre*10+wei[p])%mod,min(pk+1,k-1));
        return sum;
    }
    else
    {
        long long sum = 0;
        for(int i=0;i<=9;i++)
        {
            if(pk==0 && i==0)
            {
                sum += dfs(wei,p-1,0,0,0);
            }
            else
            {
                if(mark[i]==0)
                {
                    sum += dfs( wei,p-1,0,(pre*10+i)%mod,min(pk+1,k-1) );
                }
            }
        }
        return dp[p][pk][pre]=sum;
    }
}

long long get(long long x)
{
    if(x==0) return 1;
    memset(dp,-1,sizeof(dp));
    int wei[20];
    int cnt = 0;
    while(x)
    {
        wei[cnt++] = x%10;
        x /= 10;
    }
    return dfs(wei,cnt-1,1,0,0);
}

int main(int argc, const char * argv[]) {
    long long L,R;
    while (cin>>L>>R>>k) {
        mod = (int)pow(10.0,k-1);
        cout<<get(R)-get(L-1)<<endl;
//        int ans = 0;
//        for(int i=L;i<=R;i++)
//        {
//            int wei[10];
//            memset(wei, 0, sizeof(wei));
//            int ti = i;
//            int cnt = 0;
//            while(ti)
//            {
//                wei[ cnt++ ] = ti%10;
//                ti/=10;
//            }
//            int flag = 0;
//            for(int j=1;j<cnt;j++)
//            {
//                for(int p=1;p<k;p++)
//                {
//                    if(j-p>=0 && wei[j-p]==wei[j] )
//                    {
//                        flag = 1;
//                        break;
//                    }
//                }
//                if(flag) break;
//            }
//            if(flag == 0) ans++;
//        }
//        printf("right: %d\n",ans);
    }
    return 0;
}
/*
 1 1 2
 20 100 5
 101 101 3
 100 200 2
*/

 

转载于:https://www.cnblogs.com/chenhuan001/p/5758956.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值