HDU 5787 K-wolf Number 数位dp

题目链接:

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
", solve(y)-solve(x-1));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/fenice/p/5731315.html