qianyb
发表于 2010-5-21 11:30:55
68# wayne
本来就应该这样的,有好的方法当然要用好的
chyanog
发表于 2010-5-21 15:03:11
68# wayne
我没有作弊啊,实质其实一样的,只不过你用了Prepend附加到列表后再组成各数位不含9的数(“Prepend[#, ii] & /@ tmp”,这里不就用到了匿名函数嘛),我的只不过用了另一种途径而已,
殊途同归。
奇怪的是用NSum效率反而会下降。
wayne
发表于 2010-5-24 09:29:46
71# qianyb
:dizzy:
Buffalo
发表于 2010-6-28 21:49:43
含9的项之和收敛,因此很可能你要找的那个n不存在,盲目地找是没用的。
Buffalo
发表于 2010-6-29 16:48:08
弄错了,是不含9的项之和收敛,因此所求的n必定存在。
Buffalo
发表于 2010-6-29 17:03:57
左边分母以i(i=1..8)开头的各有10^(n-1)-9^(n-1)项,每项都不小于10^{1-n}/(i+1),以9开头的有10^(n-1)项,每项都不小于10^{-n},因此左边大于(1-0.9^{n-1})(1/2+1/3+...+1/9)+0.1。类似地,右边分母以i(i=1..8)开头的各有9^(n-1)项,每项都不大于10^{1-n}/i,因此右边小于0.9^{n-1}(1+1/2+1/3+...+1/8),要求左边大于右边的一个充分条件是(1-0.9^{n-1})(1/2+1/3+...+1/9)+0.1>0.9^{n-1}(1+1/2+1/3+...+1/8),也就是n\ge 10就够了。
同样地可以知道左边小于(1-0.9^{n-1})(1+1/2+1/3+...+1/8)+1/9,右边大于0.9^{n-1}(1/2+1/3+...+1/9),因此当n\leq 5时左边小于右边。综上,所求的n只可能是6,7,8,9,10。
以上只以分母的第一位为比较标准,如果精细一点,以前两位为比较标准,则可以得到所求的n只能是8。
chyanog
发表于 2010-11-16 20:03:57
用Mathematica又弄了一种方法,还是构造的,比前面的Mathematica版的代码要快些(计算6位以内耗时<2s):
f := Module[{t,
arr = Array &, Join[{8}, Array],
Join[{1}, Array]]},
{t = Total(*Tr@Flatten@seq*),
HarmonicNumber - HarmonicNumber - t}
]
chyanog
发表于 2010-11-16 21:44:08
最近学习了Java的字符串类,联系上了这个问题,于是又有了写出来到冲动,同时也用C#写了(大家知道,好多Java code可以稍加修改成为C#的,反之亦然)。发现Java的运行效率竟比C#快不少(网上普遍认为C#一般要比Java稍快,我私下也做过多次比较,他们都有快的时候,谁效率更高似乎没有定论),也许是我不懂C#编译优化选项的缘故。
C++的字符串函数没用过,也许比Java快吧。
另外,在我机子上的测试,相同的Java代码在Linux(我用的Ubuntu,Ubuntu10.10发布后装的)上面比Win上运行效率更高。下面的代码在Windows上面运行14s,而在Linux平台9s。
package string;
public class Is9
{
public static void main(String[] args)
{
long start = System.currentTimeMillis();
for (int n = 1;; n++)
{
long t1 = System.currentTimeMillis();
double s9 = 0.0, s0 = 0.0;
int d = (int) Math.pow(10, n - 1);
for (int i = d; i < 10 * d; i++)
{
if (Integer.toString(i).contains("9"))
//还可以用Integer.toString(i).indexOf("9")!=-1,效率稍低
s9 += 1.0 / i;
else
{
s0 += 1.0 / i;
}
}
System.out.printf("\n当n=%d时:", n);
System.out.print("s9=" + s9 + "\ts0=" + s0 + "\t");
System.out.println("Elapsed time:"+ (System.currentTimeMillis() - t1) + "ms");
if (s9 > s0)
{
System.out.println("当n=" + n + "时:s9>s0");
break;
}
}
System.out.println("\nTotal time:"+ (System.currentTimeMillis() - start) + "ms");
}
}
liangbch
发表于 2010-11-17 14:58:59
刚刚完成一个一个程序,测试表明,和gxq的速度大抵相当。
这个程序的特点是:
预先算出0-999是否含有数字9,将结果保存在1个1000个字节的数组。
算法很容易理解。
下面是源代码:
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
char bitArr;
int include9(int i)
{
char buff;
_itoa(i,buff,10);
return ( strchr(buff,'9')!=NULL);
}
int initBitArray()
{
int i;
memset(bitArr,0,sizeof(bitArr));
for (i=0;i<1000;i++)
if ( include9(i) )
bitArr=1;
return 0;
}
int sumAll(int n)
{
time_t sec;
double s9,s0;
int begin=int( pow(10.0,n-1));
int end=int( pow(10.0,n))-1;
s0=s9=0.00;
if (n<=3)
{
for (int j=begin;j<=end;j++)
{
if ( bitArr )
s9 += 1.00 /j;
else
s0 += 1.00 /j;
}
}
else
{
int base;
begin/=1000;
end/=1000;
for (int i=begin; i<=end;i++)
{
base =i*1000;
if ( include9(i) )
{
for (int j=0;j<1000;j++)
s9 += 1.00 /(double)(base+j);
}
else
{
for (int j=0;j<1000;j++)
{
if ( bitArr )
s9 += 1.00 /(double)(base+j);
else
s0 += 1.00 /(double)(base+j);
}
}
}
}
time(&sec);
printf( "n = %d\t%.24s\n", n, ctime(&sec) );
printf( "s0 = %.15f\ns9 = %.15f\ns0/s9 = %.15f\n\n\n", s0, s9, s0/s9);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
initBitArray();
for (int n=1;n<=9;n++)
{
sumAll(n);
}
return 0;
}
liangbch
发表于 2010-11-17 15:03:56
在我的电脑上,gxq 56楼的程序和我这个程序性能相当,只需7秒就得到结果。gxq,能否在你的电脑上测试一下我的这个程序?
页:
1
2
3
4
5
6
7
[8]
9
10