您的位置:首页 > 其它

HDU 5787 K-wolf Number 数位dp

2016-08-03 01:17 447 查看

题目链接:

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

K-wolf Number

Time Limit: 6000/3000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)

问题描述


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].


输入


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


输出


For each test case output a line contains an integer.


样例


sample input

1 1 2

20 100 5

sample output

1

72


题意


求L到R之间的所有的满足十进制表示中任意相邻的k位数字都不相同的数


题解


数位dp,注意处理下前导零。


代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#define bug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;

const int maxn = 20;
typedef __int64 LL;
//vector<int> 存放第i-k+1位到第i位的数
map<vector<int>, LL> dp[maxn];
int k;

//判断第0到k-2是否与k-1相同
bool ok(const vector<int>& ve) {
int last = ve[k - 1];
for (int i = 0; i < k - 1; i++) {
if (last == ve[i]) return false;
}
return true;
}

int arr[maxn],tot;
//ismax标记表示前驱是否是边界值,为true代表前驱都是边界值,为false则说明前驱已经小于边界了,这一位可以任意取了。
//iszer表示前驱是否都为0,即前面几位是否都为0
//vec记录的是前驱的结尾的k位
LL dfs(int len,vector<int> vec, bool ismax,bool iszer) {
if (len == 0) {
//递归边界,这说明前驱都合法了
return 1LL;
}
if (!ismax&&dp[len].count(vec)) return dp[len][vec];
LL res = 0;
int ed = ismax ? arr[len] : 9;
vector<int> ve;
for (int i = 1; i < vec.size(); i++) {
//这里吧前导零的部分贴成负数,防止当成真正的0来判。
if (iszer) ve.push_back(-i);
else ve.push_back(vec[i]);
}

for (int i = 0; i <= ed; i++) {
ve.push_back(i);
if (ok(ve)) {
res += dfs(len - 1, ve, ismax&&i == ed,iszer&&i==0);
}
ve.pop_back();
}
return ismax ? res : dp[len][vec] = res;
}

LL solve(LL x) {
tot = 0;
while (x) { arr[++tot] = x % 10; x /= 10; }
vector<int> vec;
for (int i = 1; i <= k; i++) vec.push_back(-i);
return dfs(tot, vec, true,true);
}

void init() {
for (int i = 0; i < maxn; i++) dp[i].clear();
}

int main() {
LL x, y;
init();
while (scanf("%I64d%I64d%d",&x,&y,&k)==3) {
printf("%I64d\n", solve(y)-solve(x-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: