[ThinkingDog]是一个积极向上、乐观、热心的人。
沉思的狗の博客
[ThinkingDog]欢迎您的光临,请多多指教!
正整数中数字1的计数问题 [C++]
/**/
/*
*******************************************************************
purpose:
在从1到n的正数中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。
例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。
求满足f(i)=i(i<=911111111099999009)这样的数总计有多少个
********************************************************************
*/
#include
<
iostream
>
#include
<
string
>
#include
<
time.h
>
using
namespace
std;
int
len;
int
*
perDigit;
//
每位上的数字
long
long
*
fullOne;
//
位数是n位的数,含1的总个数为fullOne[n]
long
long
*
addTopOne;
//
位数为n的数,首位为1时有多少个这样的数addTopOne[n] 即10^(n-1)
int
curDigit;
long
long
cnt
=
0
;
long
long
fixBit1
=
0
;
int
ocuur1Cnt
=
0
;
long
long
getOneCnt(
long
long
n)
{
len
=
0
;
while
(n
>
0
)
{
//
把数字n分成十进制串对应的数字数组
perDigit[len]
=
n
%
10
;
n
=
n
/
10
;
len
++
;
}
cnt
=
0
;
fixBit1
=
0
;
//
数字n中1所在的位被小于此位的数字重复的次数
ocuur1Cnt
=
0
;
//
数字n有几位是1
for
(
int
i
=
len
-
1
; i
>=
0
; i
--
)
{
//
从十进制数高位到低位
curDigit
=
perDigit[i];
if
(ocuur1Cnt
>
0
)
{
fixBit1
=
fixBit1
*
10
+
ocuur1Cnt
*
curDigit;
}
if
(curDigit
>
0
)
{
if
(curDigit
==
1
)
{
cnt
+=
curDigit
*
fullOne[i];
ocuur1Cnt
++
;
}
else
{
cnt
+=
curDigit
*
fullOne[i]
+
addTopOne[i];
}
}
}
return
cnt
+
fixBit1
+
ocuur1Cnt;
}
void
HowManyOne(
long
long
topNum)
{
clock_t start, finish;
//
记录计算开始结束时间
start
=
clock();
len
=
20
;
//
最长20位十进制数
perDigit
=
new
int
[len];
fullOne
=
new
long
long
[len];
addTopOne
=
new
long
long
[len];
fullOne[
0
]
=
0
;
addTopOne[
0
]
=
1
;
cnt
=
1
;
for
(
int
i
=
1
; i
<
len; i
++
)
{
//
初始化信息
fullOne[i]
=
fullOne[i
-
1
]
*
10
+
cnt;
cnt
*=
10
;
addTopOne[i]
=
cnt;
}
long
long
stack[
1000
];
//
存储数据段, [from, to]及计算方向,每次分别存入from,to,dir
long
long
lRel[
1000
];
//
符合f(i)==i表达式的i的数组
int
pStack
=
0
, pRel
=
0
;
//
stack与lRel当前长度或下一次存储位置或栈顶
long
long
from, to, dir;
//
当前要验证的一段数据的始终与验证方向,验证方向为0x01(向上) 0x10(向下) 0x11(向上向下均可以)
long
long
fn, dist;
//
fn当前一个数字n对应的1到n所有数字的十进制中的1的总个数;dist临时变量(from与to的差)
stack[
0
]
=
1
;
stack[
1
]
=
topNum;
stack[
2
]
=
3
;
//
0x11
pStack
=
3
;
int
maxP
=
0
;
while
(pStack
>
0
)
{
//
从stack中取出一段数据,验证其中的i是否满足f(i)==i
dir
=
stack[
--
pStack];
to
=
stack[
--
pStack];
from
=
stack[
--
pStack];
if
((dir
&
0x01
)
!=
0
)
{
//
UP 从from开始向to的方向计算 f(i)==i
while
(from
<=
to)
{
fn
=
getOneCnt(from);
if
(fn
>
from)
{
from
=
fn;
}
else
if
(fn
<
from)
{
from
++
;
break
;
}
else
{
lRel[pRel
++
]
=
fn;
from
++
;
}
}
}
if
((dir
&
0x10
)
!=
0
)
{
//
down 从to开始向from的方向计算 f(i)==i
while
(from
<=
to)
{
fn
=
getOneCnt(to);
if
(fn
<
to)
{
to
=
fn;
}
else
if
(fn
>
to)
{
to
--
;
break
;
}
else
{
lRel[pRel
++
]
=
fn;
to
--
;
}
}
}
if
(to
-
from
<
2
)
{
//
这一段己经很小,直接计算完
for
(;from
<=
to;from
++
)
{
if
(from
==
getOneCnt(from))
{
lRel[pRel
++
]
=
fn;
}
}
}
else
{
//
当前段向上向下己计算完,二分后入栈,再计算
dist
=
(to
-
from)
>>
1
;
dist
=
from
+
dist;
stack[pStack
++
]
=
from;
stack[pStack
++
]
=
dist;
stack[pStack
++
]
=
0x10
;
stack[pStack
++
]
=
dist
+
1
;
stack[pStack
++
]
=
to;
stack[pStack
++
]
=
0x01
;
}
}
finish
=
clock();
int
i
=
pRel;
while
(i
>
0
)
//
输出符合f(i)==i的所有i
cout
<<
lRel[
--
i]
<<
endl;
cout
<<
"
time:
"
<<
((
double
)(finish
-
start))
<<
"
ms
"
<<
endl;
cout
<<
"
total:
"
<<
pRel
<<
endl;
}
void
Test_HowManyOne()
{
HowManyOne(911111111099999009LL);
}
输出为:
199981
199982
199983
199984
199985
199986
199987
199990
199989
199988
200000
200001
1599981
1599982
1599983
1599984
1599985
1599986
1599987
1599988
1599990
1599989
2600000
2600001
13199998
35199981
35199982
35199983
35199984
35199985
35199986
35199987
35199990
35199989
35199988
35000001
35000000
35200000
35200001
117463825
500199981
500199982
500199983
500199984
500199985
500199986
500199987
500199990
500199989
500199988
500200000
500200001
501599981
501599982
501599983
501599984
501599985
501599986
501599987
501599988
501599990
501599989
502600000
502600001
513199998
535199981
535199982
535199983
535199984
535199985
535199986
535199987
535199990
535199989
535199988
535000001
535000000
500000001
500000000
535200000
535200001
1111111110
1
time: 0ms
total: 83
发表于 2011-05-25 17:51
沉思的狗
阅读(1268)
评论(3)
编辑
收藏
评论
#
re: 正整数中数字1的计数问题 [C++]
借鉴了
http://blog.csdn.net/ljsspace/archive/2011/05/22/6437981.aspx
http://topic.csdn.net/u/20110523/12/12a128ad-8a0a-4eb9-b4a1-9cda06f23e39.html?seed=1136147581&r=73511306#r_73511306
#
re: 正整数中数字1的计数问题 [C++]
楼主为什么没有main函数呢?
#
re: 正整数中数字1的计数问题 [C++]
@sf
void Test_HowManyOne()
这个函数改成main就可以了
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
Chat2DB
C++博客
博问
管理
<
2011年5月
>
日
一
二
三
四
五
六
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
导航
BlogJava
首页
发新随笔
发新文章
联系
聚合
管理
统计
随笔: 115
文章: 1
评论: 86
引用: 0
常用链接
我的随笔
我的文章
我的评论
我的参与
最新评论
留言簿
(5)
给我留言
查看公开留言
查看私人留言
随笔档案
(115)
2015年1月 (1)
2011年5月 (12)
2011年4月 (2)
2010年9月 (2)
2010年8月 (4)
2009年9月 (1)
2009年6月 (1)
2009年3月 (1)
2008年6月 (1)
2008年1月 (2)
2007年7月 (2)
2007年6月 (2)
2007年5月 (4)
2007年4月 (1)
2007年1月 (1)
2006年12月 (1)
2006年11月 (2)
2006年10月 (2)
2006年9月 (3)
2006年8月 (6)
2006年7月 (1)
2006年6月 (2)
2006年5月 (10)
2006年4月 (50)
2006年3月 (1)
网址
http://blog.csdn.net/Unagain
v_JULY_v
搜索
积分与排名
积分 - 210015
排名 - 265
最新评论
1. re: 使用Policy文件来设置Java的安全策略[未登录]
ss
--啊啊
2. re: Jni中C++和Java的参数传递
老大,Long 是J啊,不是L啊,可害苦我了,赶紧改回来吧;
--cnhua5
3. re: Jni中C++和Java的参数传递
楼主,在jni里返回String和C++里获取的为什么不一样,比如在java里看到的值是57891234,在C++里显示的是5789@,这是为什么啊?
--chr
4. re: 螺旋数字与坐标
对我的项目很有帮助。
谢谢
--cs221313
5. re: Jni中C++和Java的参数传递
long的符号表写错了,作为初学者亚历山大啊
--hhhhhh
阅读排行榜
1. Jni中C++和Java的参数传递 (63455)
2. 本地计算机上的 MSSQLSERVER 服务启动后又停止了。一些服务自动停止,如果它们没有什么可做的,例如“性能日志和警报”服务。[用批处理解决](22455)
3. 使用Policy文件来设置Java的安全策略(10482)
4. 一个简单的十六进制计算器(出自Win程序设计)(8739)
5. VC++6.0 全部默认快捷键(6198)
评论排行榜
1. Upload Server (HTTP 上传服务JAVA程序) 速度极快(11)
2. Jni中C++和Java的参数传递 (10)
3. 垃圾软件反删除批处理文件 (7)
4. 刚写的八皇后问题 - 递归 (随便你定义几个皇后了)JAVA(4)
5. 火车运煤问题(4)
[ThinkingDog]是一个积极向上、乐观、热心的人。