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
*/
时间: 2024-11-10 00:52:54

hdu5787(数位dp)的相关文章

多校5 HDU5787 K-wolf Number 数位DP

1 // 多校5 HDU5787 K-wolf Number 数位DP 2 // dp[pos][a][b][c][d][f] 当前在pos,前四个数分别是a b c d 3 // f 用作标记,当现在枚举的数小于之前的数时,就不用判断i与dig[pos]的大小 4 // 整体来说就,按位往后移动,每次添加后形成的数都小于之前的数,并且相邻k位不一样,一直深搜到cnt位 5 // http://blog.csdn.net/weizhuwyzc000/article/details/5209769

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task

hdu 5898 odd-even number 数位DP

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 716    Accepted Submission(s): 385 Problem Description For a number,if the length of continuous odd digits is even and the length

LightOJ1068 Investigation(数位DP)

这题要求区间有多少个模K且各位数之和模K都等于0的数字. 注意到[1,231]这些数最大的各位数之和不会超过90左右,而如果K大于90那么模K的结果肯定不是0,因此K大于90就没有解. 考虑到数据规模,数据组数,这题状态这么表示: dp[i][j][k]:位数为i模K结果为j且各位数之和模K结果为k的数字个数 然后就是转移方程,最后就是统计.. 统计部分好棘手...半乱搞下AC的..还是对数位DP的这一部分太不熟悉了. 1 #include<cstdio> 2 #include<cstr

HDU 4734 F(x)(数位DP)

Description For a decimal number x with n digits (A nA n-1A n-2 ... A 2A 1), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there betwe