分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相对独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
计数问题
题目描述
给定两个整数a和b,计算出1在a和b之间出现的次数。例如,如果a=1024,b=1032,那么a和b之间的数就是:
1024 1025 1026 1027 1028 1029 1030 1031 1032
则有10个1出现在这些数中。
输入:
输入不会超过500行,每一行有两个整数a和b,a和b之间的范围是0<a,b<100 000 000。输入两个0时程序结束,两个0不作为输入样例。
输出:
对于每一对输入的a和b,输出一个数,代表1出现的个数。
样例输出:
1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
0 0
样例输出:
2
185
40
666
113
105
1133
解题思路
本题要求出1在两个整数a和b之间出现的次数。可以由分治算法的思想,先求出在0~a之间出现的次数,再求出在0-b之间出现的次数,然后两者相减即可。现在的问题转换为如何求出1在0-a之间出现的次数。
将0~197的数列出来后可看出以下规律:
- 可以求出1在190~197之间出现的次数,然后对与0-189,在个位数上出现了1次。
- 个位考虑完后直接考虑197/10-1(即18中)中1出现的次数,同时考虑到,数字减小了,每一位的权值会增加,也就是说每一个数字出现的次数会增加十倍。例如,现在的1,是原来10~19之间的所有的1,即权值变为原来的十倍。
参考程序
/*本算法计算出0~9在a和b之间出现的次数,取答案时直接取d[1]即可*/
#include <iostream>
using namespace std;
/***********************************/
const int N = 11;
int d