您的位置:首页 > 其它

【POJ2282 The Counting Problem】求区间[a,b]中每个数字出现的次数

2013-04-09 21:14 381 查看
题目链接:http://poj.org/problem?id=2282

题目大意:给你两个数a,b,让你计算a到b之间所有的数总共包含多少0~9。

解题思路: 蛋疼的人生蛋疼的题。可以分别统计[0,b]中包含多少个0~9,[0,a]中包含多少个0~9,两个求得的结果相减就是答案了。

举例分析: 299 百位数字有0,1,2,那么它们在百位时分别出现了100次,再对十位数和个位数的99分析,因为[0,99]中0~9出现的频率都是一样的,

分别为2(前一个数的值)*(位数)*10(固定一个数其余位能变化的次数)。

所以对于4567,我们可以这样拆:0~3999,4000~4499,4500~4559,~4560~4567 。求得得总和就是答案了,还要注意一点的是前导0不能加进去,注意把加进去多余的前导0减掉。

#include <iostream>
#include <sstream>
#include <cstring>
using  namespace std;

///以3456分析,3456可以划分为0~2999,3000~3399,3400~3449,3450~3456
void Cal(string s, int* num)
{
int k=1;
for(int i=0; i<s.size(); i++)
k*=10, num[0]-=k;              ///去除去0作为前导的情况
for(int i=0; i<s.size(); i++, k/=10)
{
for(int j=0; j<s[i]-'0'; j++)  ///第i位时,对最高位进行分析,比如0~2999,最高位0和1都出现了1000次。
num[j]+=k;
for(int j=0; j<10; j++)  ///对0~2999分析,[0,999]中0~9出现的概率一样,最高位大小(2)*位数(3)*固定一位的最多次数(100)
num[j]+=(s[i]-'0')*(s.size()-i-1)*k/10;
for(int j=0; j<i; j++)    ///对于前面的每一位,还要后续处理后面没处理到的情况,比如处理最高位3时只处理了0~2999,而没有处理3000~3399,3400~3449,3450~3456等情况,后面处理的时候要考虑到
num[ s[j]-'0' ]+=(s[i]-'0')*k;
num[ s[i]-'0' ]++;  ///末尾都是0的情况
}
}

int main()
{
int n;
int num[10];
while(cin >> n)
{
stringstream sa;
memset(num,0,sizeof(num));
string str;
sa << n;
sa >> str;
Cal(str,num);
for(int i=0; i<10; i++)
cout << num[i] <<endl;
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐