K-wolf Number

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5787

Description

Alice thinks an integer x is a K-wolf number, if every K adjacent digits in decimal representation of x is pairwised different.

Given (L,R,K), please count how many K-wolf numbers in range of [L,R].

Input

The input contains multiple test cases. There are about 10 test cases.

Each test case contains three integers L, R and K.

1≤L≤R≤1e18

2≤K≤5

Output

For each test case output a line contains an integer.

Sample Input

1 1 2

20 100 5

Sample Output

1

72

Source

2016 Multi-University Training Contest 5

##题意:

找出区间[L,R]中有多少个数满足任意相邻的K位均不不相同.


##题解:

数位DP:分别对l-1.r求出从0开始一共有多少个数满足条件.
dp[i][j]:处理到还剩下i个数时左边相邻k个数是j(j代表一串数)的情况种数.
用map, LL> dp[maxn]来表示dp数组,vector存储左边相邻的k个数.
依次枚举每一位可能放置的数字并进行递归处理.

1. 在递归时要标记一下之前放置的那些数能否保证小于上限,如果可以当前位可以放置0-9任意数.
2. 注意处理前导零和非前导零的情况:这里用-1代表前导零,如果枚举到当前位为0时,要先看上一位是否为-1,如果是-1则当前位要更新为-1(也是前导零).
3. 记忆化:用map-dp记录下当前的计算结果. 注意:仅当当前数能确定比上限小时才能记录dp值.
(反例:比如样例的20和100,先处理100得到dp[2][-1,-1,-1]=91, 若记录下当前dp,在处理19时,则会直接返回91.)
4. 之前一直TLE是因为每次处理数据时都把dp初始化了一遍,而实际上对于所有数据dp都可以共用,只需要初始化一次即可.
5. 看到一份用五维dp数组记录的代码仅用了300ms,而上述用map-vector的记录方式用了2000ms.


##代码:
``` cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define mid(a,b) ((a+b)>>1)
#define eps 1e-8
#define maxn 55000
#define mod 1000000007
#define inf 0x3f3f3f3f
#define IN freopen("in.txt","r",stdin);
using namespace std;

int k;

int num[20];

map<vector, LL> dp[20];

bool is_ok(const vector& cur) {

int state = 0;

for(int i=0; i<k; i++) {

if(cur[i] == -1) continue;

if(state & (1<<cur[i])) return false;

else state |= (1<<cur[i]);

}

return true;

}

LL dfs(int len, vector cur, bool is_small) {

if(len == 0) return 1LL;

if(is_small && dp[len].count(cur)) return dp[len][cur];

int limits = is_small? 9:num[len];
vector<int> next; next.clear();
int sz = cur.size();
for(int i=1; i<sz; i++) {
next.push_back(cur[i]);
} LL ret = 0;
for(int i=0; i<=limits; i++) {
if(i) next.push_back(i);
else {
if(next[k-2] == -1) next.push_back(-1);
else next.push_back(0);
}
if(is_ok(next)) {
ret += dfs(len-1, next, !(!is_small&&i==limits));
}
next.pop_back();
} if(is_small) dp[len][cur] = ret;
return ret;

}

LL solve(LL x) {

int cnt = 0;

vector cur; cur.clear();

while(x) {

num[++cnt] = x % 10;

x /= 10;

}

for(int i=0; i<k; i++)

cur.push_back(-1);

return dfs(cnt, cur, 0);

}

int main(int argc, char const *argv[])

{

//IN;

LL l,r;
for(int i=0; i<20; i++) dp[i].clear(); while(scanf("%I64d %I64d %d", &l,&r,&k) != EOF)
{
//for(int i=0; i<20; i++) dp[i].clear();
printf("%I64d\n", solve(r) - solve(l-1));
} return 0;

}

HDU 5787 K-wolf Number (数位DP)的更多相关文章

  1. 多校5 HDU5787 K-wolf Number 数位DP

    // 多校5 HDU5787 K-wolf Number 数位DP // dp[pos][a][b][c][d][f] 当前在pos,前四个数分别是a b c d // f 用作标记,当现在枚举的数小 ...

  2. HDU.4352.XHXJ's LIS(数位DP 状压 LIS)

    题目链接 \(Description\) 求\([l,r]\)中有多少个数,满足把这个数的每一位从高位到低位写下来,其LIS长度为\(k\). \(Solution\) 数位DP. 至于怎么求LIS, ...

  3. HDU 5787 K-wolf Number 数位DP

    K-wolf Number Problem Description   Alice thinks an integer x is a K-wolf number, if every K adjacen ...

  4. hdu 5898 odd-even number 数位DP

    传送门:hdu 5898 odd-even number 思路:数位DP,套着数位DP的模板搞一发就可以了不过要注意前导0的处理,dp[pos][pre][status][ze] pos:当前处理的位 ...

  5. HDU 3709 Balanced Number (数位DP)

    Balanced Number Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) ...

  6. HDU 5179 beautiful number 数位dp

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5179 bc(中文): http://bestcoder.hdu.edu.cn/contes ...

  7. hdu 5898 odd-even number(数位dp)

    Problem Description For a number,if the length of continuous odd digits is even and the length of co ...

  8. HDU 5898 odd-even number (数位DP) -2016 ICPC沈阳赛区网络赛

    题目链接 题意:一个数字,它每个数位上的奇数都形成偶数长度的段,偶数位都形成奇数长度的段他就是好的.问[L , R]的好数个数. 题解:裸的数位dp, 从高到低考虑每个数位, 状态里存下到当前位为止的 ...

  9. 2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer【数位dp】

    Valley Numer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  10. HDU 4352 - XHXJ's LIS - [数位DP][LIS问题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4352 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...

随机推荐

  1. Python3 学习第三弹:异常情况如何处理?

    python 的处理错误的方式: 1> 断言 assert condition 相当于 if not condition: crash program 断言设置的目的就是因为与其让程序晚点崩溃, ...

  2. Js获取日期时间及其它操作

    var myDate = new Date();myDate.getYear();        //获取当前年份(2位)myDate.getFullYear();    //获取完整的年份(4位,1 ...

  3. Mysql的 时间戳转换 和 c# 的时间戳转换 (以秒来进行转换,非毫秒,主要是mysql不能存毫秒)

    Mysql 时间戳函数 => 从时间 转成 时间戳   UNIX_TIMESTAMP() 获取当前服务器时间的时间戳 UNIX_TIMESTAMP('2013-01-01 12:33:19') ...

  4. js 时间转成时间戳对比;My97DatePicker日历控件时间格式;Date.parse Firefox火狐浏览器返回Nan的解决办法

    有个情况,我在显示时间的时候是需要显示为  2013年8月15日 14时28分15秒 但是假如我用js去获取到这个时间,并且想进行时间对比的时候,这个时间2013年8月15日 14时28分15秒根本就 ...

  5. UVA 11090 Going in Cycle!!(二分答案+判负环)

    在加权有向图中求平均权值最小的回路. 一上手没有思路,看到“回路”,第一想法就是找连通分量,可又是加权图,没什么好思路,那就转换题意:由求回路权值->判负环,求最小值->常用二分答案. 二 ...

  6. ORACLE RAC 监听配置 (listener.ora tnsnames.ora)

    Oracle RAC 监听器的配置与单实例稍有不同,但原理和实现方法基本上是相同的.在Oracle中 tns进程用于为指定网络地址上的一个或多个Oracle 实例提供服务注册,并响应来自客户端对该服务 ...

  7. POJ 1042 Gone Fishing

    题意:一个人要在n个湖中钓鱼,湖之间的路径是单向的,只能走1->2->3->...->n这一条线路,告诉你每个湖中一开始能钓到鱼的初始值,和每钓5分钟就减少的数量,以及湖之间的 ...

  8. hdu 3047 Zjnu Stadium(加权并查集)2009 Multi-University Training Contest 14

    题意: 有一个运动场,运动场的坐席是环形的,有1~300共300列座位,每列按有无限个座位计算T_T. 输入: 有多组输入样例,每组样例首行包含两个正整数n, m.分别表示共有n个人,m次操作. 接下 ...

  9. windows各种程序中文显示乱码又找不到原因时

    我电脑上的各种程序,如xshell,Navicat for MySQL都不正常显示中文,该软件的编码,utf-8,gbk,gb2312来回切换好几回,没一次正常,最好解决办法如下       进入控制 ...

  10. 使用calabash测试开源中国Android客户端

    Calabash-android是支持android的UI自动化测试框架,前面已经介绍过<中文Win7下成功安装calabash-android步骤>,这篇博文尝试测试一个真实应用:开源中 ...