由100盏灯想到的(二)

本系列的第一篇:

http://www.cnblogs.com/dhf327/p/4773672.html

100盏灯的问题,上次我们算是基本解决了,不管算法上是否够优化,至少我们已经在可接受的时间得到了答案。

但是最后还留了一道题,亲们,你们是不是已经想出来了?

一,上次的题目

上一篇给出了python求一个正整数的所有的因数的方法,这个方法目前工作正常,求单个正整数的所有因数速度上也没有任何问题。

但是结合上一篇最后的题目,有心的同学一下子就看出问题来了,1到10的12次方,假设求每个数的所有因数需要1毫秒,整个循环总共需要多长时间?(考虑到后期的数字比较大,前期的数字比较小,这个1毫秒还是比较乐观的时间)

python可以快速计算一下:

1 print(1000000000000/1000/60/60/24/365)

结果是 >31.7  这个数的单位应该是吧,我的老天,不是在逗我玩吧。这个时间任谁也接受不了,这个QQ群咱们不加了?

显然,就算我们使用并行算法,在可接受的时间内,仍不能得到正确的结果。也许可以用集群来处理,又好像大炮打蚊子了。

此时需要算法优化了。

二,再谈算法优化

当常现方式不能解决的时候,我们需要一种新的思路来解决这个问题,因为这基本是个纯数学问题,而我的数字功底一般,那就请出万能的搜索引擎吧,找到两个相关的定理可以用到。

约数个数定理,约数和定理。这里的约数也就是因数。百度百科的解释如下:

对于一个大于1正整数n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
则由约数个数定理可知n的正约数有(a?+1)(a?+1)(a?+1)…(ak+1)个,
那么n的(a?+1)(a?+1)(a?+1)…(ak+1)个正约数的和为
f(n)=(p1^0+p1^1+p1^2+…p1^a1)*(p2^0+p2^1+p2^2+…p2^a2)*…*(pk^0+pk^1+pk^2+…pk^ak)

如10=2^1*5^1;  则10的因数个数为 (1+1)*(1+1)=4个,因数和为(2^0+2^1)+(5^0+5^1)=18

上面定理的内容没有提到,一般的p1<p2<p3...

证明可以自己去找资料,总之这个内容我们是可以拿来用了。

如果用这个定理,似乎可以解决我们的问题了,让我们试试看。

三,分解质因数

每个数要分解质因数,也就是质数的因数,忘记质数定义的同学请自行百度,

假设我们有从2开始的连续的质数有序序列,我们可以很快的计算出一个数分解质数的结果。

m=[2,3,5,7,11,13,17,19,...]

假设对n进行分解质因数,那么就是从2开始,如果能整除,就用整除后的值再除以2,如果除不尽的时候,就除以下一个值3,依次类推,直到分解完毕。

这就是有名的短路算法。

让我们来比较一下,上一篇中我们求所有的因数的算法,可以真正求出一个正整数的所有的因数,而现在利用这个公式,我们可以不用求出所有的因数,就能直接对所有的因数进行求和,似乎是更快了一些。

实际上,上一篇中的算法不依赖任何其他的东西,只是计算量比较而已,虽然只是从2到n的平方根,但这其中的每个数都要参与运算,计算量很大。

此时新的短路算法,看起来比较快,但是还有很重要的一点,他需要一个质数的序列!

问题似乎变复杂了。

未完待续)

时间: 2024-08-26 10:34:45

由100盏灯想到的(二)的相关文章

由100盏灯想到的(一)

原题目地址:http://www.cnblogs.com/DeanChopper/p/4772593.html 大厅里有100盏灯,每盏灯都编了号码,分别为1-100.每盏灯由一个开关来控制.(开关按一下,灯亮,再按一下灯灭.开关的编号与被控制的灯相同.)开始时,灯是全灭的.现在按照以下规则按动开关.第一次,将所有的灯点亮.第二次,将所有2的倍数的开关按一下.第三次,将所有3的倍数的开关按一下.以此类推.第N次,将所有N的倍数的开关按一下.问第100次按完以后,大厅里还有几盏灯是亮的. 网上找了

100人100盏灯(详解)

题:一百盏灯排成一排,初始状态是亮的, 编号为 1-100,100个人编号1-100.每个人从1号灯开始逐次走过这100盏灯.每个人只拉他对应编号的倍数的灯,问最后亮着几盏灯? 这是一道很经典的笔试题.频繁出现.下面是比较简洁的实现代码.已验证. 1 package 笔试; 2 3 public class 完全平方数100人和灯 { 4 public static void main(String[] args) { 5 boolean[] light=new boolean[100]; 6

js:自动亮起100盏灯

1)    使用js在页面上显示100盏灯,并标记从1到100的编号2)    页面加载后3秒,从编号是1的灯依次自动亮起.3)    每过0.5秒亮下一盏灯(10分)4)    所有灯亮起后,弹出确认框,询问是否要关闭页面5)    点确定,页面自动关闭.点取消,页面不动. <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html

还有几盏灯?

大厅里有100盏灯,每盏灯都编了号码,分别为1-100.每盏灯由一个开关来控制.(开关按一下,灯亮,再按一下灯灭.开关的编号与被控制的灯相同.)开始时,灯是全灭的.现在按照以下规则按动开关. 第一次,将所有的灯点亮. 第二次,将所有2的倍数的开关按一下. 第三次,将所有3的倍数的开关按一下. 以此类推.第N次,将所有N的倍数的开关按一下. 问第100次按完以后,大厅里还有几盏灯是亮的. 解答: 这题和数字的因数个数有关.例如:12=1*12=2*6=3*4,所以1,2,3,4,6,12就是12的

屋子里有1到100号100盏关闭的灯

屋子里有1到100号100盏关闭的灯,门外有1到100号100个人,每个人都要进屋一次,把与自己序号对应的和是自己序号倍数的灯绳拉一下,(比如1号要拉所有的灯绳,2号要拉2,4,6的灯绳,而100号只需拉100号灯绳)问:当100人都出来后,屋子里亮着的灯有几盏? 这么说呢,大家都知道答案是 平方数 1,4,9...100 ok,首先要想到肯定是拉灯拉了奇数次的才能是打开的...想想如果编号为N,那么肯定是前面拉过N的i必定能整除N,所以肯定i是N的因数...所以题目转换为求N,N的因数的个数是

现在有100个标记过的电灯泡。第一个人经过这些灯时,点亮所有的灯,第二个人经过时每隔一盏灯就切换开关一次,第三个人经过时每隔两盏灯切换开关一次。请问,当第100个人经过时,还剩多少盏亮着的灯?

做了一个草图:10(纵10人)X10(横10栈灯) 第一个人:1 1 1 1 1 1 1 1 1 1第二个人:0 1 0 1 0 1 0 1 0 1第三个人:0 0 1 0 0 1 0 0 1 0第四个人:0 0 0 1 0 0 0 1 0 0第五个人:0 0 0 0 1 0 0 0 0 1第六个人:0 0 0 0 0 1 0 0 0 0第七个人:0 0 0 0 0 0 1 0 0 0第八个人:0 0 0 0 0 0 0 1 0 0第九个人:0 0 0 0 0 0 0 0 1 0第十个人:0 0

哪个开关控制哪盏灯

QUESTION: 房间里面有三盏灯,屋外有三个开关,分别控制着三盏灯,只有进入房间,才能看到哪盏灯是亮的.请问如何只进入房间一次,就能指明哪个开关控制哪盏灯??? ANSWER: 假设开关编号为A,B,C.打开开关A,但不进入房间:等过了大约若干分钟后,关闭开关A,并且打开开关B:同时迅速进入房间内,并且用手摸房间内不亮的两盏灯以确定哪盏灯发热.设[房间内亮着的灯.不亮但温度较高的灯.不亮但温度较低的灯]的编号分别为L1.L2.L3. 判断的结果是:开关A控制L2:开关B控制L1:开关C控制L

从150盏灯这道奥数题说起......

前段时间,成都9岁学生纠错奥赛名题这篇文章在网上爆红.本文不关注神童之类的新闻,仅仅从计算机实现的角度来验证题目正确性. 题目描述(需求描述): 150盏亮着的电灯,各有一个拉线开关控制,按顺序编号为1,2,3,-,150.将编号为3的倍数的灯的拉线各拉一下,再将编号为5的倍数的灯的拉线各拉一下,拉完后亮着的灯数为__盏. 使用暴力穷举法来获得正确答案: 为了简单期间,我们可以将150盏灯缩小10倍,变为15盏灯,这样就很容易用暴力穷举法来标记出灯的最终结果: 答案: 第一遍拉灭3的倍数,15÷

轻松学习JavaScript四:JS点击灯泡来点亮或熄灭这盏灯的网页特效映射出JS在HTML中作用

我们开始解释JS在HTML中作用.对于因特网和视窗操作系统,JavaScript都意味着未来. (1)JavaScript:写入HTML输出 实例代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://ww