Beautiful Natural Number(ACM)

Problem description
You are given two integer numbers N and M, and your task is to calculate how many integer numbers satisfy the following two conditions.
1): This integer number is not less than 0, and is not great than N;
2): The sum of the digit of this integer number is not great than M;
We define this kind of number as beautiful natural number.
For example, give you N = 13, M = 3, then the corresponding result is Tot= 7, and the following 7 numbers are beautiful natural numbers: 0, 1, 2, 3, 10, 11, 12. Now give you two numbers N and M, can you tell me the value of Tot?

 
Input
The input consists of several test cases. Each case of the input contains only one line, two integer numbers N and M. you may assume that 0 <= N < 10^9, 0 <= M <100. The input ends with EOF.
 
Output
For each test case, print one line containing the value of Tot.
 
Sample Input
13 3
3 5
5 3
0 25
145623 99
Sample Output
7
4
4
1
145624

 

#include <iostream>
#include <sstream>
using namespace std;
int t[10][101];//位数为i,位数的和最大为j 
void CountLess(int l, int m){
	int maxx,minn,get;
	for(int i=2;i<l;i++){ //前i位 
		for(int j=1;j<=m;j++){//限制为j 
			maxx=min(j,9);
			//选取数字 
			get=0;
			for(int k=0;k<=maxx;k++){
				get+=t[i-1][j-k];//i-1位数字,j-k的限制下Tot数量 num&k
			}
			t[i][j]=get;
		} 
	}
}
int Tot(long long n,int m){
	int i,j,k,l,minn,maxx,get1,get2;
	stringstream ss;
	string str;
	ss<<n;
	ss>>str;
	l=str.length();
	//位数小于l 
	//以1开头计算 
	//限制为0 
	for(i=0;i<=l;i++){
		t[i][0]=0; 
	}
	//位数为0、1	
	for(i=0;i<=m;i++){
		t[0][i]=0;//前0位,0个 
		t[1][i]=min(i,9);//前1位,限制i,9中较小的 
	}

	CountLess(l,m);
	get1=0;
	for(i=1;i<l;i++){
		get1+=t[i][m];
	} 
	//位数等于l
	//可以以0开头,再计算 
	for(i=0;i<=m;i++){
		t[1][i]=min(i+1,10);//前1位限制为i:  0  0,1  0,1,2……i+1
	}
	for(i=1;i<=l;i++){
		t[i][0]=1;//前i位限制为0: 0 00 000 0000 00000…… 
	} 
	CountLess(l,m);
	int MaxSum=m,num,off=0;
	get2=0;
	for(i=1;i<=l;i++){
		num=str[i-1]-'0';
		minn=(i==1?1:0);
		maxx=min(MaxSum,num-1);//[0/1,MaxSum/num-1]
		if(l-i==0) off=1;
		for(j=minn;j<=maxx;j++){
			get2+=(t[l-i][MaxSum-j]);//后l-i位,限制是MaxSum-j
			get2+=off;
		}
		MaxSum-=num;
		if(MaxSum<0) break;
	}
	if(MaxSum>=0&&n) get2++;
	return get1+get2;
}
int main(){
	int n,m;
	while(cin>>n){
		cin>>m;
		cout<<Tot(n,m)+1<<'\n';
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hnu哈哈

请接受直女的么么哒????

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值