2602 数字计数

2602 数字计数

一般像这种数位DP,都是像这样给定区间,对区间进行操作,对于这道题的题意不难理解,就是统计区间0~9的个数
看不出来和动态规划有什么关系
这道题很难推出来递推公式,因为很难想到怎么求第几位的数字是多少,因为不能有前导零
f[i]表示在有i位数字的情况下,每个数字有多少个,如果不考虑前导0,你会发现对于每一个数,他的数量是相等的,也就是f[i]=f[i-1]×10+10i-1
对于DP这个东西,最重要的其实就一点,推状态,什么是状态?是大问题的子问题,对于DP很重要的就是无后效性,问题可以拆分,并且答案具有一定的规律,这样就能DP了
数位DP最重要的就是把一整个数字拆分成一位一位的单独来看,所以对于数位DP,他的子问题就是求每一位答案求解

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int SIZE=30;
ll a,b;
ll log[SIZE];//计算10的次幂 
ll f[SIZE];//代表在有i位数字,每一位数字有多少个 
ll cnta[SIZE],cntb[SIZE];
void sol(ll x,ll *cnt)
{
	ll num[20]={0};//转换数位 
	int len=0;
	while(x)
	{
		num[++len]=x%10;
		x=x/10;
	}
	for(int i=len;i>=1;i--)//枚举位数 
	{
		for(int j=0;j<=9;j++)//求代表数字个数 
			cnt[j]+=f[i-1]*num[i];//A*f[i-1] 
		for(int j=0;j<num[i];j++)
			cnt[j]+=log[i-1];
		ll num2=0;
		for(int j=i-1;j>=1;j--)
		{
			num2=num2*10+num[j];//计算前导零的情况
			//10*i-1*i-2*i-3*i-4 
		}
		cnt[num[i]]+=num2+1;
		cnt[0]-=log[i-1];
	}
}
int main()
{
	cin>>a>>b;
	log[0]=1;
	for(int i=1;i<=15;i++)
	{
		f[i]=f[i-1]*10+log[i-1];//计算f数组 
		log[i]=10*log[i-1];//计算10次幂 
	}
	sol(a-1,cnta);
	sol(b,cntb);
	for(int i=0;i<=9;i++)
		cout<<cntb[i]-cnta[i]<<" ";
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值