hdu4722 Good Numbers 规律题

Good Numbers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3839    Accepted Submission(s): 1224


Problem Description
If we sum up every digit of a number and the result can be exactly divided by 10, we say this number is a good number.
You are required to count the number of good numbers in the range from A to B, inclusive.
 

Input
The first line has a number T (T <= 10000) , indicating the number of test cases.
Each test case comes with a single line with two numbers A and B (0 <= A <= B <= 10 18).
 

Output
For test case X, output "Case #X: " first, then output the number of good numbers in a single line.
 

Sample Input
  
  
2 1 10 1 20
 

Sample Output
  
  
Case #1: 0 Case #2: 1
Hint
The answer maybe very large, we recommend you to use long long instead of int.
 

开始可以暴力打印一些出来看看,注意0能够被10整除

0 - 100  10

0 - 1000  100

0 - 99 10

0 - 91 10

0 - 90 9

可以发现有近似num / 10的规律,仔细观察后发现其实确实粗略来看是每10个出现一个和为10的倍数


因为对于一个十位数,例如1X,这时候个位只有10 - 1 = 9才满足,对于一个三位数例如12X,则由于1和2是确定的,所以在120 - 129这十个数的范围内(也就是个位0 - 9)只有10 - 1 - 2 = 7,即127满足,对于大一点的数,例如637859X,6 + 3 + 7 + 8 + 5 + 9 = 38,因为最后一位肯定只能为正(不可能为-8),所以只有最后一位为40 - 38 = 2,即6378592符合条件,所有的数都这么看,会发现每次高位确定了,其实在个位上只有0 - 9当中的一个数能够满足,这就印证了num / 10的规律


最后只要注意下右边界就行了,即

0 - 90 -> 90 / 10 = 9个

但是

0 - 91 ->90 / 10 + 1 = 10个(由于91这个边界多加了一个)

处理方法是从90 / 10 * 10 = 90 -->91暴力扫一下,看有没有多出来一个能够满足各位和是10的倍数的,发现91是,所以就在9的基础上加1,因为我们证明了个位0 - 9有且只有一个数满足,所以只要扫过去发现一个直接返回就行了


#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

long long get(long long num) {
	long long n = num / 10 * 10;
	bool flag = false;
	for (; n <= num; n++) {
		long long tn = n, sum = 0;
		while (tn) {
			sum += tn % 10;
			tn /= 10;
		}
		if (sum % 10 == 0) {
			flag = true;
			break;
		}
	}
	if (flag)
		return 1;
	else
		return 0;
}

long long solve(long long num) {
	if (num < 0) return 0;
	if (num < 10) return 1;
	return num / 10 + get(num);
}



int main()
{
	int T;
	long long a, b;
	scanf("%d", &T);
	for (int t = 1; t <= T; t++) {
		scanf("%I64d%I64d", &a, &b);
		printf("Case #%d: %I64d\n", t, solve(b) - solve(a - 1));
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值