主题:求数字和(符合要求的回答都给30分)
jyf1987
[专家分:930] 发布于 2005-08-12 08:51:00
这里的数字和与数和是2码事
题目是这样的
输入一个数,求从1到该数的所有数的数字的和
例如:输入12
应该求1+2+3+4+5+6+7+8+9+1+0+1+1+1+2
一般的解决方案是把每个数拆开,然后慢慢算,但这种方法效率低,算到上千万时就要花点时间了,我想用数学方法总结规律来做,可是我的那个方法对于整百,整千,整万……的算不出来,只有各个数位都不为0时才可以算,不过速度超快,算几十万那么多时间,几十亿也是那么多时间
请各位大侠不吝赐教!!!!!!!!!!!!
30分啊,你不心动么?呵呵
回复列表 (共32个回复)
21 楼
jyf1987 [专家分:930] 发布于 2005-08-17 09:42:00
我可能表达意思有问题,但是确实和你说的一样的思路
下面那个是我的代码。老是有问题,痛苦啊。应该说方法没错,我自己代了个数笔算了下,不出问题,但代码就出问题了,
DIM s#
INPUT a: s# = 0
t$ = LTRIM$(STR$(a)): t = LEN(t$): DIM p%(t)
FOR i = t TO 1 STEP -1
p(i) = VAL(MID$(t$, i, 1))
NEXT i
FOR j = t TO 2 STEP -1
IF p(j) = 0 THEN GOTO a
IF p(j) = 1 THEN
s# = s# + p(j) * 45 * (j - 1) * 10 ^ (j - 2) + VAL(RIGHT$(t$, j - 1)) + 1
ELSE
k = p(j) * (p(j) - 1) / 2
s# = s# + p(j) * 45 * (j - 1) * 10 ^ (j - 2) + k * 10 ^ (j - 1) + (VAL(RIGHT$(t$, j - 1)) + 1) * p(j)
END IF
a: NEXT j
PRINT s# + (1 + p(1)) * p(1) / 2
大家帮帮忙吧
22 楼
jyf1987 [专家分:930] 发布于 2005-08-17 10:16:00
假设有个数a(n)a(n-1)…a(2)a(1)[设为p]
我们从第n位计算起
由于从0到99……9[n-1个9]是有公式可以一步计算出来的[设计算结果为k],那么我们可以利用k来计算从0到(a(n)-1)99……9[n-1个9前面是a(n)-1],其实从0到我们截止的这个数,0到99……9[n-1个9]是重复出现的,所不同的是前面的数字不同,那么0到我们截止的这个数中k出现了几次呢,答案是a(n)次,比如3214中,0到999出现了3次,同时,第n位上的数字各自又出现了10^(n-1)次,比如0到299百位的1出现了100次,2也出现了100次,所以从0到我们截止的这个数的数字和应该是a(n)*k+(1+2+…+a(n)-1)*10^(n-1)[结果1],但是第n位上还有些数字没有算完,从我们截止的这个数到p这其中a(n)出现了a(n-1)a(n-2)…a(2)a(1)+1次,
所以可以计算出数字和是a(n)*val(right$(ltrim$(str$(p)),n-1))[结果2]
计算出结果1和结果2后,剩下来的就是计算从0到a(n-1)a(n-2)…a(2)a(1)的数字和
这又可以用刚刚上面哪个方法了,(这是递归还是嵌套?我不记得定义了)
这就是我上面代码的原理,可是我的代码老是出问题
23 楼
zqnhlm [专家分:780] 发布于 2005-08-17 10:24:00
楼主签名里的那张照片好像杀人犯!!!
24 楼
jyf1987 [专家分:930] 发布于 2005-08-17 10:29:00
那是我的照片,在网吧里抓的
25 楼
moz [专家分:37620] 发布于 2005-08-17 12:38:00
1. 我觉得我说的够清楚的了.
2. 除了缩写的程序外,我原来写的程序也不难
3. 我觉得你说得一塌糊涂,除了我,我认为再没有其他人能理解得到了.
4. 先说说你的"研究思路"
5. 再说说你的代码.
4. 请比较一下你表达的和我表达的区别
a 为某一个需要计算的多位数整数值, f(a)为求 a 的数字累积和函数
根据若干位全9 (999....9) 的数值的和可快速求得,
所以把 a 分解成全9的和:
比如: 3214 = f(999) + f(999)+1000*1 + f(999)+1000*2 + f(214)+215*3
(0带头时) (1带头时) (2带头时) (3带头时)
分解完后把 f(214) 以同样的函数处理计算 (自我调用叫递归)
214 = f(99) + f(99)+100*1 + f(14)+ 15*2
继续分解 f(14)
这里有一个问题,就是你计算f(999)的时候是否按照我告诉过你的式子?
f(n个9)=45 * n * 10^(n-1)
3214=4500*3*3+1000*1+1000*2+3*215 + 450*2*2+100*1+2*15 + 45*1+1*5 + 1+2+3+4
=46135
5. 有了正确的思路写不出正确的代码,那说明什么?
找出源程序中错误的地方,如果你不把代码贴出来谁知道你对错,错在哪?
A)
IF p(j) = 0 THEN GOTO a
.....
a: next
完全可以改为:
if p(j)=0 then
elseif p(j)=1 then
else
endif
B) 用双精度的数会不会出现小数点呢? 奇怪.
C) 不用STEP 的 for 效率会更好
D)
IF p(j) = 1 THEN '[color=FF00FF]为什么1就要单独处理呢?[/color]
s# = s# + p(j) * 45 * (j - 1) * 10 ^ (j - 2) + VAL(RIGHT$(t$, j - 1)) + 1
ELSE [color=FF00FF]\为什么不直接代1进去?[/color]
k = p(j) * (p(j) - 1) / 2 '这是小于P(j)的累积和
s# = s# + p(j) * 45 * (j - 1) * 10 ^ (j - 2) + k * 10 ^ (j - 1) + (VAL(RIGHT$(t$, j - 1)) + 1) * p(j)
END IF
PRINT s# + (1 + p(1)) * p(1) / 2
E) 我已经没有心情改了,影响了我吃饭的胃口,等你全部推倒重新写过再说吧,假如我没理解错你的思路的话.幸好你不是教师,否则我估计不少好学生需要自杀.等我吃完饭再来搞.
26 楼
moz [专家分:37620] 发布于 2005-08-17 13:23:00
好了,终于清楚了
1. 我不喜欢那么多冒号,什么道理就不说了.
2. 你那个 IF 是多余的,我也不喜欢
3. 你最大的错误是弄错数字的顺序
4. 我改过来你自己慢慢看,看不明白不要问我,你的变量我都不改了
DIM s#
INPUT a: s# = 0
t$ = LTRIM$(STR$(a)): t = LEN(t$): DIM p%(t)
FOR i = t TO 1 STEP -1
p(i) = VAL(MID$(t$, [color=FF00FF]t-i+1[/color], 1))
NEXT i
FOR j = t TO 1 STEP -1
k = p(j) * (p(j) - 1) / 2
s# = s# + p(j) * 45 * (j - 1) * 10 ^ (j - 2) + k * 10 ^ (j - 1) + (VAL(RIGHT$(t$, j - 1)) + 1) * p(j)
NEXT j
PRINT s#
27 楼
zqnhlm [专家分:780] 发布于 2005-08-17 14:12:00
汗
28 楼
★神 [专家分:880] 发布于 2005-08-18 20:44:00
8楼的错误:
endif中间得有空格的!
LET也可以不用的!
先算MOD,再算+、-的!
还有一点也不全面的!
楼主也太那个什么了哇!!!!
29 楼
moz [专家分:37620] 发布于 2005-08-18 23:35:00
开启语法检查的QB会自动把endif分开来的
既然 let 也可以不用,那就是说用也没有错啊
先算 mod 再算 + - , def 已经是老手了,这也没有错,
还有一点也不全面? 还有什么不全面的?
def 是写错了,但却偏偏都不是你说的那些地方错,很是奇怪.
30 楼
jyf1987 [专家分:930] 发布于 2005-08-21 15:11:00
用1是因为出1计算公式不一样
不过我觉得moz太过了,我就喜欢钻研,学的是gvb语言,还不完全懂
才学没几天,那天有个小孩找我问这个题目,我做了那个用循环的给他,但是执行确实很慢,于是几想这个方法,我就一菜鸟,许多语句都还不会,无非是想学点东西
那问题对于moz来说当然容易,那代码对于moz来说当然烦琐,不过,我想谁一开始就那么厉害呢
我来回复