Luogu P2602 [ZJOI2010]数字计数

洛谷P2602数字出现次数解析
本文详细解析洛谷P2602题目,探讨如何计算指定范围内所有整数中每个数字出现的频率。通过深度优先搜索(DFS)的方法,使用C++实现并分享代码细节。

https://www.luogu.org/problemnew/show/P2602

题目描述

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

输入输出格式

输入格式:

 

输入文件中仅包含一行两个整数a、b,含义如上所述。

 

输出格式:

 

输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

 

输入输出样例

输入样例#1: 复制

1 99

输出样例#1: 复制

9 20 20 20 20 20 20 20 20 20

说明

30%的数据中,a<=b<=10^6;

100%的数据中,a<=b<=10^12。

 

 

 

啊啊啊啊,离联赛只差没几天的,菜鸡仍然在RE边缘徘徊,诶,太惨了

菜鸡在这儿立志要学习DFS版的,否则尽情来喷我吧,骂不还口

 

求解的时候没有考虑原来的数本身的数字,就吊死在题头

 

#include<cstdio>
#define ll long long
using namespace std;

ll l,r;
const int N=20;

struct A
{
	ll f[N][N][N];
	int a[N];
	inline void pre()
	{
		for(int i=0;i<=9;i++) f[1][i][i]=1;
		for(int i=2;i<=13;i++)
			for(int j=0;j<=9;j++)
			{
				ll num=1;
				for(int ii=1;ii<i;ii++) num*=10;
				f[i][j][j]+=num;
				for(int k=0;k<=9;k++)
					for(int l=0;l<=9;l++) f[i][j][l]+=f[i-1][k][l];
			}
	}
	
	ll sum(ll x,int bj)
	{
		int len=0; ll ret=0;
		while(x) a[++len]=x%10,x/=10;
		for(int i=1;i<len;i++)
			for(int j=1;j<=9;j++) ret+=f[i][j][bj];
		for(int i=1;i<a[len];i++) ret+=f[len][i][bj];
		int num0=0;
		if(a[len]==bj) num0++; 
		for(int i=len-1;i;i--)
		{
			ll num=1;
			for(int k=i-1;k;k--) num*=10;
			for(int j=0;j<a[i];j++) 
				ret+=f[i][j][bj]+num*num0;
			if(a[i]==bj) num0++;
		}
		return ret;
	}
}DP;

int main()
{
	DP.pre();
	scanf("%lld%lld",&l,&r);
	for(int i=0;i<=9;i++) 
		printf("%lld%c",DP.sum(r+1,i)-DP.sum(l,i),(i==9)?'\n':' ');
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值