项目欧拉问题233

时间:2009-03-08 11:29:05

标签: algorithm math geometry diophantine

接下来我决定解决Project Euler problem 233,但我遇到了一些重大问题!我做了一些分析并取得了一些相当不错的进展,但我现在已经陷入困境。这是我的工作:

引理1 : 由于圆圈经过4个角点,因此任何n都至少有4个解。但是对于圆周上的每个点,有7个其他点被发现有反射。因此总有8k + 4个格点。

引理2 : 圆具有半径(√2)n和中心(n / 2,n / 2),因此其方程为(x-n / 2)^ 2 +(y-n / 2)^ 2 = [n/√2] ^ 2。这减少到x ^ 2 + y ^ 2 = n(x + y)。

引理3 : 如果写入x ^ 2 + y ^ 2 = n(x + y)的解(x,y,z),则另一解是(kx,ky,kz)。证明是:

(x+y)n = x^2+y^2

(kx)^2+(ky)^2 = (kx+ky)m
k(x^2+y^2) = (x+y)m
m = kn

这与我对这一思路的影响一样多 - 我看不到任何地方可以从那里去,但它包括在内,因为它可能很有用。

我的下一个想法是移动圆圈的中心。将有相同数量的解决方案在任何维度上移动整个整数。所以当n / 2是整数时,所以n = 2k,x ^ 2 + y ^ 2 = 2 * k ^ 2。而且事实证明,这个等式的解决方案与方程x ^ 2 + y ^ 2 = k ^ 2一样多(见Sloane A046109)。

这也提供了一种简单的方法来计算任何n通过A046080的解决方案的数量。如果4k + 1形式的n中素数的幂是f [0] ... f [m],那么解的数量是4 *乘积(2f [i] +1 | i in [0 .. .M])。

这允许我向后工作:4.product(2f [i] +1 | i in [0 ... m])= 420,所以乘积(2f [i] +1 | i in [0 .. .m])= 105 = 3 * 5 * 7。我能够想出这个程序,我认为找到所有n的总和,形式为2k且小于10 ^ 11,其中有420个圆格点。答案(我希望!)是257199853438240692。

这是C程序:

#include "stdlib.h"
#include "stdio.h"
#include "math.h"
#include "string.h"

#define lim 1000000000L

char prime[lim];
long primes[50000000];
long len = 0;

int main(void)
{
    long i, j;
    for(i = 0; i < lim; i++)
    {
        prime[i] = 1;
    }

    for(i = 2; i < lim; i++)
    {
        if(prime[i])
        {
            for(j = 2*i; j < lim; j += i) prime[j] = 0;
            if((i-1)%4 == 0)
            {
                prime[i] = 2;
                //printf("%li\n", i);
                primes[len++] = i;
            }
        }

        if(i < 1000 || (i < 10000 && i%1000 == 0) || i%10000 == 0) printf("%li, %li\n", i, len);
    }

    printf("primes!\n");

    long a, b, c, v, total = 0, k;
    for(a = 0; a < len; a++)
    {
        v = primes[a]*primes[a]*primes[a];
        if(v > 50000000000L) break;

        for(b = 0; b < len; b++)
        {
            if(b == a) continue;

            v = primes[a]*primes[a]*primes[a]*primes[b]*primes[b];
            if(v > 50000000000L) break;

            for(c = 0; c < len; c++)
            {
                if(c == a) continue;
                if(c == b) continue;

                v = primes[a]*primes[a]*primes[a]*primes[b]*primes[b]*primes[c];
                if(v > 50000000000L) break;

                for(k = 1; k*v <= 50000000000L; k++)
                {
                    if(prime[k] == 2) continue;
                    total += k*v;
                }
            }
        }
    }

    for(a = 0; a < len; a++)
    {
        v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a];
        if(v > 50000000000L) break;

        for(b = 0; b < len; b++)
        {
            if(b == a) continue;

            v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[b]*primes[b]*primes[b];
            if(v > 50000000000L) break;

            for(k = 1; k*v <= 50000000000L; k++)
            {
                if(prime[k] == 2) continue;
                total += k*v;
            }
        }
    }

    for(a = 0; a < len; a++)
    {
        v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a];
        if(v > 50000000000L) break;

        for(b = 0; b < len; b++)
        {
            if(b == a) continue;

            v = primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[a]*primes[b]*primes[b];
            if(v > 50000000000L) break;

            for(k = 1; k*v <= 50000000000L; k++)
            {
                if(prime[k] == 2) continue;
                total += k*v;
            }
        }
    }

    printf("%li\n", 2*total);


    return 0;
}

我们只需要添加具有420个圆格点的n的值,并且形式为2k + 1!然而,这似乎比n = 2k更难,我看不到任何方法。我也有点不确定我的答案是否正确,因为这个方法很复杂......任何人都可以证实吗?是否有一种简洁的方法,不涉及不同的n处理?

我完全没有想法!


我最感兴趣的是我如何处理N = 2k + 1,因为当N = 2k时,我可以像John Feminella所说的那样做。

3 个答案:

答案 0 :(得分:9)

提示1:圆的半径为n /√2,对于整数n从不是整数,因此A046080永远不会适用。

提示2:不要打扰周围的圆圈。从方格纸上拿起它,然后想一想,定义它的方块,以及相对于彼此的圆周上尚未知的兴趣点。

提示3:半圆内接的角度始终为90度。

提示4:一个数字可以写成两个方格的总和?

奖金提示在整个过程中自由使用:对称!


SPOILER ALERT!


在您尝试从上面的提示中解决之前,请不要进一步阅读

如果这些提示不够,以下是与上述提示交错的一些缺失步骤:

提示1.5:由于您使用的方法基于有缺陷的前提,因此您将不得不改变查看问题的方式。

提示2.5:想想广场顶角之间弧线左侧的格点。通过对称,在它的右边有另一个这样的点,而在下面直接有第三个点。关于这些点之间的距离以及它们形成的角度,你能说些什么呢?

提示3.5:如何确定任何给定n的正方形顶角之间弧的左侧有多少个格点?

答案 1 :(得分:1)

提示#1。你的引理#2不太正确。你确定这是半径吗?

提示#2。答案与平方和函数r(k,n)密切相关。这给出了使用k个不同方块表示n的方式的数量,允许零并区分顺序。例如,r(2,5)是8,因为有8种方法用2个方块表示5:

(-2)^2 + (-1)^2
(-2)^2 + 1^2
2^2    + (-1)^2
2^2    + 1^2
... (and the 4 additional expressions produced by reversing these 2 terms)

您可以看到以原点为中心的半径为p的圆具有r(2,p ^ 2)点阵点。例如,半径为5的圆具有:

(-4)^2 + (-3)^2
... and 7 others like this

5^2    + 0^2
(-5)^2 + 0^2
0^2    + 5^2
0^2    + (-5)^2

总共12个。什么类型的数字会有420个圆格点?如果他们不是以原点为中心呢?我会让你从这里拿走它。

如果你想要一个更大的提示,我已经腐烂了13(http://rot13.com)你应该在这里查看:

uggc://zngujbeyq.jbysenz.pbz/FpuvamryfGurberz.ugzy

答案 2 :(得分:0)

您可以参考http://oeis.org/A046109/b046109.txt来检查多达1000个。我在这里安装了PARI / GP并使用了一种PARI脚本:http://oeis.org/A046109检查更高的数字。