Digital Count数位统计

B -- Digital Count

Time Limit:1s Memory Limit:1024MByte

Submissions:522Solved:117

DESCRIPTION

Given three integers a, b, P, count the total number of digit P appearing in all integers from a to b.

INPUT
The first line is a single integer TT, indicating the number of test cases.
For each test case:
There are only three numbers a,b,Pa,b,P (0≤a≤b≤2 31-1, 0<P<10).
OUTPUT
For each test cases:
Print the total appearances of digit PP from aa to bb in a single line.
SAMPLE INPUT
2
1 10000 1
1 10 1
SAMPLE OUTPUT
4001
2




思路,预处理1位,2位,3位,...,n位的情况

定义f(i,j)为i开头后面跟着j位的范围为 i*10^j~(i+1)^j-1内p出现的次数

举例来说f(2,1))表示20~29范围内出现p的次数

所以有下列递推式:

当 j ≠ p --> f[ i , j ] = Σ f[ k, j-1 ]k=0..9     

当 j = p --> f[ i , j ] = Σ f[ k, j-1 ]k=0..9 + 10j





AC源码:

#include <iostream>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#include <algorithm>
typedef long long LL;
using namespace std;

const int MAXN=10;
LL f[MAXN][MAXN];

void init(int p)
{
	for(int i=0;i<=9;++i)
		f[i][0]=0;
	for(int j=0;j<=9;++j)
		if(j==p)
			f[j][0]=1;
	for(int j=1;j<=9;++j)
	{
		for(int i=0;i<=9;++i)
		{
			for(int k=0;k<=9;++k)
			{
				f[i][j]+=f[k][j-1];
			}
			if(i==p)
				f[i][j]+=pow(10,j);
		}
	}
}
LL count(int n,int p)
{
	queue<int> que;
	stack<int> stk;
	int num=n;
	while(num>0)
	{
		stk.push(num%10);
		num/=10;
	}
	while(!stk.empty())
	{
		que.push(stk.top());
		stk.pop();
	}
	num=n;
	LL cnt=0;
	while(!que.empty())
	{
		int len=que.size();
		if(len==1)
		{
			for(int i=0;i<=que.front();i++)
				cnt+=f[i][len-1];	
			break;
		}
		for(int i=0;i<=que.front()-1;i++)
			cnt+=f[i][len-1];
		if(que.front()==p)
			cnt+=num-que.front()*pow(10,len-1)+1;
		num=num-que.front()*pow(10,len-1);
		que.pop();
	}
	return cnt;
}

void show()
{
	for(int j=0;j<=9;++j)
	{
		for(int i=0;i<=9;++i)
		{
			cout<<f[i][j]<<" ";	
		}
		cout<<endl;
	}
	
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		memset(f,0,sizeof(f));
		int a,b,p;
		cin>>a>>b>>p;
		init(p);
//调试
//		show();
		cout<<count(b,p)-count(a-1,p)<<endl;
	}
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值