- 题目描述:
亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他。问题是:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
- 输入:
输入有多组数据,每组测试数据为一行。
每一行有两个整数a,b(0<=a,b<=1,000,000,000)。
- 输出:
对应每个测试案例,输出a和b之间1出现的次数。
样例输入:
0 5
1 13
21 55
31 99
样例输出:
1
6
4
7
【解题思路】对于给定一个数,算包含的1的个数,我们可以将这个数分为很多部分,然后分别算1的个数。首先我们很容易得到一个n位数中1的个数,n位数1的个数等于n-1位数中1的个数与10相乘加上第n位为1的额外增加的个数pow(10,n-1)。
例如给定105,可以从第一位开始计算,首先是两位数0-99中1的个数,然后是100-105中首位1的个数为6,然后到第二位0,不计算。第三位5,计算0位数1个数0个,然后计算1这个数1的个数为1。最后将所有计算结果相加。
AC code:
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <cstring>
#include <cstdlib>
using namespace std; int clude(string &str,const int&k)
{
int re=0;
for(int i=k;i<str.length();++i)
re=re*10+str[i]-'0';
return re;
} int cal(const int &tt,const vector<int> &numidx)
{
if(tt<=0)
return 0;
int all=0;
int idx;
char strc[15];
sprintf(strc,"%d",tt);
string str(strc);
for(int i=0,j=str.length()-1;i<str.length();++i,--j)
{
idx=str[i]-'0';
if (idx==0)
continue;
else if(idx==1)
{
all+=clude(str,i+1);
++all;
all+=numidx[j];
}
else
{
all+=pow(10.,j);
all+=numidx[j]*idx;
}
}
return all;
} int main()
{
int a,b;
vector<int> numidx(13,0);
numidx[1]=1;
for(int i=2;i<13;++i)
numidx[i]=numidx[i-1]*10+pow(10.,i-1);
while(cin>>a>>b)
{
if(a<b)
printf("%d\n",cal(b,numidx)-cal(a-1,numidx));
else
printf("%d\n",cal(a,numidx)-cal(b-1,numidx));
}
return 0;
}
/**************************************************************
Problem: 1373
User: huo_yao
Language: C++
Result: Accepted
Time:40 ms
Memory:1520 kb
****************************************************************/题目链接:http://ac.jobdu.com/problem.php?pid=1373 九度-剑指Offer习题全套答案下载:http://download.csdn.net/detail/huoyaotl123/8276299