有人可以向我解释为什么下面的算法是一个无差错的整数分解方法,总是返回N的非平凡因子。 我知道这听起来有多奇怪,但是我在2年前设计了这种方法,但仍然不理解它背后的数学逻辑,这使我难以改进它。这很简单,只涉及加法和减法。
public static long factorX( long N )
{
long x=0, y=0;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;
while ( a!= 0 )
{
a-= ( 2+2*x++ - y);
if( a<0 ) { a+= (x+b+1); y++; }
}
return ( x+b+1 );
}
似乎上述方法实际上通过迭代到丢番叶方程找到了解决方案:
f(x,y) = a - x(x+1) + (x+b+1)y
where b = floor( sqrt(N) ) and a = b(b+1) - N
that is, when a = 0, f(x,y) = 0 and (x+b+1) is a factor of N.
Example: N = 8509
b = 92, a = 47
f(34,9) = 47 - 34(34+1) + 9(34+92+1) = 0
and so x+b+1 = 127 is a factor of N.
重写方法:
public static long factorX(long N)
{
long x=1, y=0, f=1;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;
while( f != 0 )
{
f = a - x*(x+1) + (x+b+1)*y;
if( f < 0 ) y++;
x++;
}
return x+b+1;
}
我真的很感激有关如何改进这种方法的任何建议。
以下是10个18位随机半实数的列表:
349752871155505651 = 666524689 x 524741059 in 322 ms
259160452058194903 = 598230151 x 433211953 in 404 ms
339850094323758691 = 764567807 x 444499613 in 1037 ms
244246972999490723 = 606170657 x 402934339 in 560 ms
285622950750261931 = 576888113 x 495109787 in 174 ms
191975635567268981 = 463688299 x 414018719 in 101 ms
207216185150553571 = 628978741 x 329448631 in 1029 ms
224869951114090657 = 675730721 x 332780417 in 1165 ms
315886983148626037 = 590221057 x 535201141 in 110 ms
810807767237895131 = 957028363 x 847213937 in 226 ms
469066333624309021 = 863917189 x 542952889 in 914 ms
答案 0 :(得分:2)
好的,我用Matlab看看这里发生了什么。这是N = 100000的结果:
您在每次迭代时增加x
,而a
变量的有趣模式与其余N % x+b+1
密切相关(正如您在图的灰线中所见,{{1 }})。
因此,我认为你只是通过简单的迭代找到大于a + (N % (x+b+1)) - x = floor(sqrt(N))
的第一个因子,但是用一个相当模糊的标准来确定它真的是一个因素:D
(对不起半答案......我必须离开,我可能会在以后继续)。
这是matlab代码,以防您希望自己进行测试:
sqrt(N)
答案 1 :(得分:1)
您的方法是(n-a)*(n + b)的试验乘法的变体,其中n = floor(sqrt(N))和b == 1.
算法然后迭代a - / b ++直到(n-a)*(n + b) - N == 0的差异。
部分差异(关于a和b)分别与2b和2a成比例。因此,不需要真正的乘法。
复杂性是| a |的线性函数或| b | - N越“平方”,方法收敛得越快。总之,有更快的方法,最容易理解的是二次残留筛。
答案 2 :(得分:0)
原谅我的#,我不懂Java。 将x和y步进2可提高算法速度。
{{1}}&#13;