牛客小白月赛8: E. 诡异数字(数位DP)

版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/83218360

链接:https://www.nowcoder.com/acm/contest/214/E
来源:牛客网
 

题目描述

有一天clccle在家里玩手机,突然手机上出现了一个诡异的黑影,眼里闪烁着白光,发出了奇怪的声音(像是正常的声音倒放之后再正放的样子),clccle努力辨别后终于听懂了这个黑影在说什么,大概如下,给定你一个区间[l,r]和多个约束,
请你求出在这个区间内满足这个约束的数字个数(不含前导零),如果clccle不能在1s内求出这个答案,就会被送入一个奇怪的旅馆(Rusty Lake Hotel),因为clccle很害怕,请你帮她在1s之内求出这个答案

输入描述:

注意:此题有多组数据

第一行,一个整数T,代表数据组数

对于每组数据,

有三个数字 l,r,n

接下来n行,每行一个数字x,接下来一个数len表示数字x在数字串中连续出现的次数不能大于len

输出描述:

对于每组数据

输出一个整数,表示l,r中满足约束的数字个数。(对20020219取模)

输入

2
0 50 2
4 1
4 4
0 100 2
4 1
5 1

输出

50
99

强行诡异。。

很裸的一个数位DP,dp[len][x][sum]表示当前长度为len,上一个数字是x,且已经连续出现了sum次的合法数字个数

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int str[24], most[24];
LL dp[24][12][24];
LL Sech(int len, int now, int sum, int flag)
{
	LL ans;
	int u, i;
	if(sum>most[now])
		return 0;
	if(len==0)
		return 1;
	if(flag==0 && dp[len][now][sum]!=-1)
		return dp[len][now][sum];
	if(flag==1)  u = str[len];
	else  u = 9;
	ans = 0;
	for(i=0;i<=u;i++)
	{
		if(i==now)
			ans += Sech(len-1, now, sum+1, flag&&i==u);
		else
			ans += Sech(len-1, i, 1, flag&&i==u);
	}
	if(flag==0)
		dp[len][now][sum] = ans;
	return ans;
}
LL Jud(LL x)
{
	int len = 0;
	len = 0;
	if(x==-1)
		return 0;
	while(x)
	{
		str[++len] = x%10;
		x /= 10;
	}
	return Sech(len, 0, 0, 1);
}
int main(void)
{
	LL l, r;
	int T, n, x, y, i;
	scanf("%d", &T);
	while(T--)
	{
		memset(dp, -1, sizeof(dp));
		scanf("%lld%lld%d", &l, &r, &n);
		for(i=0;i<=9;i++)
			most[i] = 99999;
		for(i=1;i<=n;i++)
		{
			scanf("%d%d", &x, &y);
			most[x] = min(most[x], y);
		}
		printf("%lld\n", (Jud(r)-Jud(l-1))%20020219);
	}
	return 0;
}
/*
125
0 236927938 0
*/

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/83218360