出个题目给大家练一下,纯算法

daidodo 2007-12-06 02:53:46
问题:在32 bits可表示的所有整数中(0-4294967295)中,有多少个整数包含2,例如2,12,123是包含2的;1,13,134是不包含2的。

你的算法可以计算包含3的个数吗?0呢?

如果把范围扩大,比如64 bits范围,128 bits范围,你的算法还能快速计算出结果吗?
...全文
209 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
HW121 2007-12-07
  • 打赏
  • 举报
回复
如果是求某个正整数N以内的整型数中含数字a的数的个数,先求无数字a的数的个数M:
N = Cn-1*10^(n-1) + ... + Ci+1*10^(i+1) + Ci*10^i + ... + C0
Ni = Cn-1*10^(n-1) + ... + Ci+1*10^(i+1)
m(i) Ni至N之间无数字a的数的个数
无数字a的数的i位数的个数为9^(i-1) 所以
一、a!=0
1、Ci = a m(i) = a*9^(i-1)
2、Ci < a m(i) = m(i-1) + Ci*9^(i-1)
3、Ci > a m(i) = m(i-1) + (Ci-1)*9^(i-1)
二、a=0 如果把0~10^(n-1)内的数都补0变成n位数可以按 一处理,因前面0不算则多处理了
1*9*9^(n-2)+1*9*9^(n-3)+...+9*1+1 个数所以需要补上
#include   <stdio.h> 
#include <stdlib.h>

typedef long int int32;

int32 containFig(int32 n, int fig)
{
int c;
int32 s, powm = 1, m = 1, m0 = 0;

for(s = n; s; s /= 10, powm *= 9)
{
if((c=s%10) == fig)
m = fig*powm;
else
{
if(c > fig) c--;
m += c*powm;
}
m0 += powm;
}
if(!fig)
m += m0;
return (n+1-m);
}


void main(int argc, char *argv[])
{
int32 N = 100000000L;
int fig = 0;
while( scanf("%d %d", &N, &fig) == 2)
printf( "%d contain %d char number = %d, %d\n", N, fig, containFig(N, fig), containFig2(N, fig));
}

HW121 2007-12-07
  • 打赏
  • 举报
回复
呵呵,楼主的算法与5楼一样,7楼还补充0的算法, 都是先求无这个数字的数的个数。
daidodo 2007-12-07
  • 打赏
  • 举报
回复
我把我的方法说出来吧:

2^32 - 1 = 4294967295,共10位数
算所有不包含2的数字个数:
最高位为:0,1,3的10位数里,不包含2的数字有:3 * 9^9个(其他位都可以为0,1,3,...,9)
如果最高位为4,那么次高位(第9位)可以为0,1,此时不包含2的数字有:2 * 9^8
如果最高2位是42,无论怎样都包括2了
于是最终结果就是 2^32 - 3 * 9^9 - 2 * 9^8

用心算可以得到结果。

基本上对于任意整数N,只要知道它各位上的数字和位数就行了。
例如对于64 bits整数,最大N = 18446744073709551615,共20位,那么所有不包含2的数字个数:
2^64 - (1 * 9^19 + 7 * 9^18 + 3 * 9^17 + 3 * 9^16 + .... )

HW121 2007-12-06
  • 打赏
  • 举报
回复
楼上的含0时的算法有问题,先下班。
HW121 2007-12-06
  • 打赏
  • 举报
回复
以前做过含数字1的数的个数http://topic.csdn.net/u/20070818/19/b6ad5b88-d343-4a43-9fd6-e8ec3feb7925.html, 改改可以算数字1~9的数的个数
// 如果是求某个正整数N以内的整型数中含数字a的数的个数,那就用归纳法: 
// 同样先求正整数N以内无数字1的数的个数M
// N = Cn-1*10^(n-1) + ... + Ci+1*10^(i+1) + Ci*10^i + ... + C0
// Ni = Cn-1*10^(n-1) + ... + Ci+1*10^(i+1)
// m(i) Ni至N之间无数字a的数的个数
// Ci 取0~Ci个数字
// 1、Ci = a m(i) = a*9^(i-1)
// 1、Ci < a m(i) = m(i-1) + Ci*9^(i-1)
// 3、Ci > a m(i) = m(i-1) + (Ci-1)*9^(i-1)

// 由m(0)则可计算出m(n-1) 故 N以内的整型数中含数字1的数的个数 = N + 1 - m(n-1)
// m(0) = (C0 < a) ? C0 : C0-1 也可
// m(0) = fig*9^0 C0=a
// (C0-1)*9^0+1 C0> 1
// (C0-1)*9^0+1 C0> 1


#include <stdio.h>
#include <stdlib.h>

typedef long int int32;

int32 containFig(int32 n, int fig)
{
int c;
int32 s, k = 0, powm = 1, m = 1;

for(s = n; s; s /= 10, powm *= 9, k++)
if((c=s%10) != 0)
{
if(c == fig)
m = fig*powm;
else
{
if(c > fig) c--;
m += c*powm;
}
}
if(!fig)
for(powm = 1 ; --k; powm *= 10)
m += powm;
return (n+1-m);
}

void main(int argc, char *argv[])
{
int32 N = 100000000L;
int fig = 1;
while( scanf("%d %d", &N, &fig) == 2)
printf( "%d contain %d char number = %d, %d\n", N, fig, containFig(N, fig), containFig2(N, fig));
}
daidodo 2007-12-06
  • 打赏
  • 举报
回复
这边回复就是快!呵呵

ls两位的方法只能说“可以算出来”,但是不是最简单的方法。
我所知道的最简单的方法,只要给定一个范围N,用心算可以很快得到结果表达式,然后用计算器可以得到数字结果。
pptor 2007-12-06
  • 打赏
  • 举报
回复
用组合方法直接就可以计算出来
bits可表示的所有整数中(0-4294967295)
最高位为2的 其他位不管(最高位后面可以为000000000----9999999999)10^9
最高位 不为2,次高位为2 的也可以简单的计算出 最高为为1,3是,次高位后面什么数字都可以排列有2*10^8
再加上 最高为4 有(00000000---94967295)
最高位 次高位 不为2(共有20钟情况) 第三高位为2,从第四位到最后一位什么数字都可以排(0000000--9999999) 10^7
所以最高位 次高位 不为2() 第三高位为2 有20×10^7
以下高四位不为2 第5位为2 ,也是根据上面情形计算
对于64 bits范围,128 bits范围 主要就是计算他的最大值 通过这个最大值 按上述情形分析
Tiger_Zhao 2007-12-06
  • 打赏
  • 举报
回复
[0,9]: 1
[0,99]: 1*10 + 9*1 = 19
[0,999]: 1*100 + 9*19 = 271

即:求区间[0,10^n-1]中出现2的整数个数
f(n)
=1 当n=1时
=10^(n-1) + 9 * f(n-1) 当n>1时

g(0,4294967295)
=g(0,3999999999) + g(0,199999999) + g(200000000,294967295)
=10^9 + 3*f(10) + 2*f(9) + 294967296
gemenhao 2007-12-06
  • 打赏
  • 举报
回复
O(1) 时间计算出
对每一位计算个数最后统计。

33,007

社区成员

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

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