给出一个区间 统计0-9 出现的次数

fx397993401 2009-08-03 04:26:30
比如 10-19 1出现 11次 其余出现1次
由于 会给出很大的区间 所以我们要找出规律
有大牛 有过类似的经验 给我一点启发

比如 00 -99 我们就可以不用算也知道 每个数字都是出现了 20次 这里面有它的一般规律
对于给出的区间我们可以分成适合计算的区间 比如 2- 1287
可以分成 2 -99 100 -999 1000 - 1199 1200 - 1287

这样算出就比较简单 但是实现 有点问题 大家可以给出更好的 或对于我的思路给出建议 弄了一天了
...全文
390 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
fireseed 2009-08-04
  • 打赏
  • 举报
回复
看了以前的贴子,有些思路是很好的,但没有优秀的实现。这里随手写了一个,看起来效率非常高,实际上不管多大的数,只要是int能表示的,都是瞬间就出结果。

测试是另写了一个递归法的求解函数,保证正确的情况下,测试两函数的值是否相等。用10万个随机数测了一下,暂时没发现问题。但是递归函数不能算很大的数,所以大数没办法测,如果有问题敬请指正!



#include <math.h>
#include <iostream>
using namespace std;

// 以下函数计算由a到b,出现数字n的次数
int main( int argc, char* argv[] )
{
int a = 101, b = 202, n = 0;

// 如果输入非法,退出函数,返错错误码-1
if ( a >= b || n > 10 || a < 0 || n < 0 || n > b ) return -1;
int r = ( a == 0 && n == 0 ); // 如果n和a均为0,那么a=0时计1次
// 下面将从最高位到最低位进行计算,统计n在每一位出现的次数
// nPower为与b等数量级的10^x,将b取10的对数,向下取整再加1即为幂x
for ( int nPower = (int)pow( 10.0, floor( log10( (double)b ) ) + 1 );
nPower >= 10; nPower /= 10 ) // 每次循环结束后将nPower减一个数量级
{ // nTop和nBottom分别表示此次计算数值域的上界和下界
// 比如b为12345,统计6,现在计算第3位,那么nTop应为12600
int nTop = ( b / nPower ) * nPower + n * ( nPower / 10 );
int nBottom = ( a / nPower ) * nPower + n * ( nPower / 10 );
// 如果nTop大于b,就将高一位减1,如:12600>12345,则减为11600
if ( nTop > b ) nTop -= nPower; // 因为只有xx600才能在第三位出现6
// 如果nBottom加上分段长度仍小于a,或出现0的特殊情况,则将高位加1。
if ( nBottom + nPower / 10 - 1 < a || ( n == 0 && nBottom < nPower ) )
nBottom += nPower;
// 如果上下界的值正常,则进行统计运算
if ( nTop > nBottom || ( nBottom / ( nPower / 10 ) % 10 <= n &&
n <= nTop / ( nPower / 10 ) % 10 ) )
{ // 以下算法详见说明
r += ( nTop / nPower - nBottom / nPower + 1 ) * ( nPower / 10 );
if ( nTop + nPower / 10 - 1 > b ) r -= nTop + nPower / 10 - 1 - b;
if ( nBottom < a ) r -= a - nBottom;
}
}
cout << r << endl;
}
ToBeTough 2009-08-03
  • 打赏
  • 举报
回复
刚看过 !再温习下 !
绿色夹克衫 2009-08-03
  • 打赏
  • 举报
回复
以前讨论过很多次了,LZ看看这个帖子吧,帖子里还连接了以前更老的帖子!

http://topic.csdn.net/u/20090326/16/a98028cc-25e3-479d-851c-6a8e1f552f82.html
fireseed 2009-08-03
  • 打赏
  • 举报
回复
00027 到
58345

比如统计5出现的次数

在最低位,5出现了(5834 - 0002 - 1 + 1)次,-1是因为7>5,+1是因为7到5出现一次5
第二位,5出现了(583 - 000)次,2到4不出现5
第三位,5出现了(58 - 00)次,0到3不出现5
第四位,5出现了(5 - 0 + 1)次,+1是因为0到8出现一次5
第五位,显然有1次

那么把上面的值相加就可以了,可以写出程序了吧?不会超过15行,算法复杂度为o(log10(n))

33,025

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧