Algorithm 将给定的数字表示为四个平方和
我正在寻找一种算法,它将给定的数字表示为(最多)四个平方的和 例子 120=82+62+42+22Algorithm 将给定的数字表示为四个平方和,algorithm,math,Algorithm,Math,我正在寻找一种算法,它将给定的数字表示为(最多)四个平方的和 例子 120=82+62+42+22 6=02+12+12+22 20=42+22+02+02 我的方法 取平方根,对剩余部分重复此操作: while (count != 4) { root = (int) Math.sqrt(N) N -= root * root count++ } 但当N为23时,即使有一个解决方案,也会失败: 32+32+22+12 问题: 有没有其他算法可以做到这一点 这总是可能
6=02+12+12+22
20=42+22+02+02 我的方法 取平方根,对剩余部分重复此操作:
while (count != 4) {
root = (int) Math.sqrt(N)
N -= root * root
count++
}
但当N为23时,即使有一个解决方案,也会失败:
32+32+22+12
问题:
这是一个简单的
4
循环的解决方案
max = square_root(N)
for(int i=0;i<=max;i++)
for(int j=0;j<=max;j++)
for(int k=0;k<=max;k++)
for(int l=0;l<=max;l++)
if(i*i+j*j+k*k+l*l==N){
found
break;
}
max=平方根(N)
对于(inti=0;i它总是可能的——这是数论中的一个定理,叫做“拉格朗日四平方定理”
为了有效地解决这一问题,本文给出了一种在预期O((logn)^2)时间内运行的方法
这里有关于实施的有趣讨论:
通过找到。是否始终可行?
是的,缔约国指出:
每个自然数都可以表示为四个整数平方的和
这已经在几个方面得到了证明
算法
有一些更智能的算法,但我建议使用以下算法:
将数字分解为素数因子。它们不必是素数,但越小越好:因此素数是最好的。然后按如下所示解决这些因子中的每一个的任务,并将得到的任何4个平方与之前找到的4个平方和组合在一起
(a2+b2+c2+d2)
(A2+B2+C2+D2)=
(aA+bB+cC+dD)2+
(aB)− bA+cD− dC)2+
(aC)− 屋宇署− 钙+分贝)2+
(公元前+公元前− cB− dA)2
给定一个数字n(上述因素之一),得到不大于n的最大平方,然后查看n减去该平方是否可以写成三个平方的和,使用:这是可能的,当且仅当该数字不是以下形式时:
4a(8b+7)
如果这个方块不合适,试试下一个较小的方块,直到你找到一个为止。它保证会有一个方块,而且大多数方块都会在几次重试后找到
尝试以与步骤1相同的方式找到一个实际的第二个平方项,但现在测试其可行性,扩展使用它意味着:
如果n与3模4全等的素因子都是偶数指数,那么n可以表示为两个平方和,反之亦然
如果这个正方形不合适,试试下一个较小的,直到你找到为止。保证会有一个
现在我们减去两个平方后有一个余数。试着减去第三个平方,直到得到另一个平方,这意味着我们有一个解决方案。这一步可以通过首先分解最大的平方因子来改进。然后当两个平方项被识别时,每个平方项可以再次乘以该平方的平方根除数
这大致就是这个想法。为了找到主要因素,有以下几种。下面我将使用
这是JavaScript代码,因此您可以立即运行它--它将生成一个随机数作为输入,并显示为四个平方和:
函数除数(n,因子){
var除数=1;
而(n%系数==0){
n=n/系数;
除数=除数*因子;
}
返回除数;
}
函数getPrimesUntil(n){
//素筛算法
变量范围=数学地板(数学sqrt(n))+1;
var isPrime=数组(n).填充(1);
var素数=[2];
对于(var m=3;m0;sq1--){
n2=n1-sq1*sq1;
//一个数字可以写成三个平方和
//它不是表4^a(8b+7)
如果((n2/除数(n2,4))%8!==7)中断;//发现了一种可能性
}
//2.找到合适的第二个正方形
对于(sq2=数学地板(数学sqrt(n2));sq2>0;sq2--){
n3=n2-sq2*sq2;
//一个数字可以写成两个平方和
//其形式为4a+3的所有素因子都具有偶数指数
factors3=素数。因式分解(n3);
ok=正确;
对于(系数3中的f3){
ok=(f3.value%4!=3)| |(f3.count%2==0);
如果(!ok)中断;
}
如果(ok)中断;
}
//要节省时间,请从以前的因式分解中提取最大的平方因子:
sq=1;
对于(系数3中的f3){
sq*=数学功率(f3.value,(f3.count-f3.count%2)/2);
f3.count=f3.count%2;
}
n3/=sq*sq;
//3.找一个合适的第三方
sq4=0;
//b.找到剩余值的平方:
对于(sq3=数学地板(数学sqrt(n3));sq3>0;sq3--){
n4=n3-sq3*sq3;
//看看这是否会产生两个平方和:
sq4=数学地板(数学sqrt(n4));
如果(n4==sq4*sq4)中断;//是!
}
//将平方除数合并回步骤3的结果中:
sq3*=sq;
sq4*=sq;
//4.将这四个正方形与之前的任何四个正方形合并
//使用Euler平方恒等式,我们得到了四倍:
而(f.count--){
[res1,res2,res3,res4]=[
Math.abs(res1*sq1+res2*sq2+res3*sq3+res4*sq4),
Math.abs(res1*sq2-res2*sq1+res3*sq4-res4*sq3),
Math.abs(res1*sq3-res2*sq4-res3*sq1+res4*sq2),
Math.abs(res1*sq4+res2*sq3-res3*sq2-res4*sq1)
];
}
}
//按降序返回4个方块(为方便起见):
返回[r]