| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2395 人关注过本帖
标题:projecteuler.net 系列问题转贴
只看楼主 加入收藏
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
http://www.

黄金分割比太简单了。随便一个link都有很详细的说明。
2011-06-27 13:31
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 30楼 Devil_W
我没说完贴啊,我想等一等。我也不想完贴

重剑无锋,大巧不工
2011-06-27 13:32
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
我就是想看看你那个偶数fib和的推导过程,

肿么,你在卖关子
2011-06-27 13:35
a9580643
Rank: 2
来 自:江西九江
等 级:论坛游民
帖 子:60
专家分:59
注 册:2011-4-21
收藏
得分:0 
程序代码:
#include <stdio.h>
int main()
{
    int a,c=0;
    for(a=0;a<1000;a++)
        if((a%3==0)||(a%5==0))c=c+a;
        printf("他们的和是%d\n",c);
        return 0;
}
只会第一题- -。

[ 本帖最后由 a9580643 于 2011-6-27 23:04 编辑 ]

花有重开日,人无在少年。
2011-06-27 23:02
q279838089
Rank: 2
等 级:论坛游民
帖 子:16
专家分:21
注 册:2011-6-22
收藏
得分:0 
回复 13楼 jimmywood
long long num
我的vc6.0报错了
是不是应该用数组来存储12位的数字
2011-06-29 20:23
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 Devil_W
呵呵,看来不解释一下算法都对不起仁兄的置顶卡了。不知道仁兄的置顶卡哪来的...

进入正题

首先要更正一下Fibonacci数列的起始项,应该是

1, 1, 2, 3, 5, 8, 13, 21,...

现在讨论每一项的奇偶性质。

根据数列的定义,每一项是前两项的和。那么该项的奇偶性与前两项有关。

对于两个数的和有下面的性质(别嫌简单)

奇 + 奇 = 偶
奇 + 偶 = 奇
偶 + 奇 = 奇
奇 + 奇 = 偶

由此数列的奇偶序列是

奇 奇 偶 奇 奇 偶 奇 奇 偶 ...

(这也是一个有限状态自动机)

由此也证明Fibonacci数列每三项出现一个偶数。

因为每个偶数都是它前面两个奇数的和,所以某偶数项之前的偶数和就是全部和的一半。

为了讨论方便,定义几个常数

A = (1 + √5) / 2
B = (1 - √5) / 2
C = 1 / √5

这样,Fibonacci的通项公式就是

F(n) = C * (A^n - B^n)

n 是项的索引,也可以叫序号,从1开始。

换个符号更顺眼一些。

F(x) = C * (A^x - B^x)

对于前 N 项的和就是求F(x)在[1,N]的积分。。。。
开个玩笑,这个问题用不着做积分。当然,其本质就是积分。
前 x 项的和为

sum(F(x)) = sum(C * (A^x - B^x))
          = C * (sum(A^x) - sum(B^x))

而sum(A^x)是一个初始值为A,比率为A的等比数列,它前x项的和为

sum(A^x) = A * (A^x - 1) / (A - 1)

同理

sum(B^x) = B * (B^x - 1) / (B - 1)

将它们以及A B C代入F(x)整理一下就得到我算法中最后那个求和公式

现在的问题就是如何根据已知的项值 A 求出它对应的索引 x

也就是求F(x)的反函数F^-1(x)

这本来是个理想的方法,但不得不承认毕业太久了,我的数学水平退步了。

我用了两个小时也没有得到一个显式的反函数,只能得到隐函数。

虽然用迭代法也可以从隐函数中求得 x,但消耗的计算量是我不能接受的,也不想为这么简单的问题动用这么复杂的算法。

于是我着手简化原函数,用一个近似函数代替原函数。

注意F(x) 中 B^x 这个幂函数。

B 是一个小于 0 大于 -1 的负数, B^x 是一个振荡函数。

为了便于讨论,换个写法

B^x = (-1)^x * (-B)^x

这样,(-1)^x 是一个符号函数(x的定义域是自然数集),0 < -B < 1

当 x 增大时 (-B)^x 减小趋于 0,而且速度很快。这一点可以有很严格的数学证明,这里我就不废话了。

基于此,我略去了原函数中这一项得到一个近似函数

Q(x) = C * A^x

它的反函数就很简单了

Q^-1(x) = ln(x / C) / ln(A)

用它我可以代入项值求出一个近似的索引值,就是算法中的第一句

由于我们由于我们已知的值也不是一个真正的项值,真正的项值可能比这个值小,但下一项的值一定比这个值大。

得到的索引值也是一个近似值。

所以算法的中间部分就是对这个近似索引值的修正,以得到精确的索引值。

其实之前发的代码是错误的,只是很偶然得到了正确的结果。现在发修正后的代码。

仁兄可以对比一下,有兴趣的话仁兄来解释一下为什么

程序代码:
int Test2(int a)

 {
     double x, y, sf;
     int n, t;
     
     x = log(SQRT_5 * a) / log(A);
     x += 0.5;
     n = (int)x;
     y = (pow(A, n) - pow(B, n)) / SQRT_5;
     y += 0.5;
     t = (int)y;
     if(t > a) n--;
     n -= n % 3;
     sf = ((SQRT_5 + 1) / (SQRT_5 - 1) * (pow(A, n) - 1) - (1 - SQRT_5) / (1 + SQRT_5) * (1 - pow(B, n))) / SQRT_5;
     sf += 0.5;
     
    return ((int)sf) / 2;

 }


不知道分析明白没,有质疑我们还可以再讨论

重剑无锋,大巧不工
2011-06-29 22:13
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 35楼 q279838089
VC6.0中没有long long这个类型,可以用__int64
输出时用cout也会出错。可以C函数来输出printf("%l64d", num);

重剑无锋,大巧不工
2011-06-29 22:16
Devil_W
Rank: 10Rank: 10Rank: 10
等 级:青峰侠
威 望:9
帖 子:1160
专家分:1797
注 册:2009-9-14
收藏
得分:0 
实在不想看你那证明,很明显我第一眼看到你的code就知道你在凑数。

你码了那么多字我 就觉得 奇偶性是你最突出的证明。

也就是F(3k) 都是偶数。

http://mathworld.

根据这个链接的第89和第90项结论,你的code很明显是错误的。
只要令x=1,a=3,b=0就能把sum(F(3k)算出来了。 这个式子怎么化也不可能跟你那玩意一样。
2011-06-30 11:36
小乙哥
Rank: 2
等 级:论坛游民
帖 子:15
专家分:27
注 册:2011-5-30
收藏
得分:0 
程序代码:
1.
# include<stdio.h>

int main(void)
{
    int i = 0;
    int j = 0;

    for(i = 0; i < 1000; i++)
    {
        if(i%3 == 0 || i%5 == 0)
            j = j + i;
    }
    printf("%d\n", j);

    return 0;
}
2.
int main(void)
{
    int a = 1;
    int b = 0;
    int c = 0;
    int d = 0;

    for(; ;)
    {
        c = a + b;
        a = b;
        b = c;

        if(c%2 == 0)
            d = d + c;
        if(c > 4000000)
            break;
    }
     printf("%d\n", d);

    
    return 0;
}
第三题不懂
2011-07-02 20:13
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
楼主的头像看着有点吓人。

我就是真命天子,顺我者生,逆我者死!
2011-07-03 16:48
快速回复:projecteuler.net 系列问题转贴
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.035955 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved