[英]Is there an algorithm, to find values of a polynomial with big integers, quickly without loops?
例如,如果我想找到
1085912312763120759250776993188102125849391224162 = a^9+b^9+c^9+d 代碼需要帶上
一=3456
b=78525
c=217423
d=215478
我不需要具體的值,只要符合a、b和c最多6位,d盡可能小的事實即可。
有沒有快速找到的方法?
我很感激你能給我的任何幫助。
我嘗試過嵌套循環,但它非常慢並且代碼卡住了。
VB 或其他代碼中的任何幫助將不勝感激。 我認為在這種情況下結構比語言更重要
Imports System.Numerics
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Value As BigInteger = BigInteger.Parse("1085912312763120759250776993188102125849391224162")
Dim powResult As BigInteger
Dim dResult As BigInteger
Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim d As Integer
For i = 1 To 999999
For j = 1 To 999999
For k = 1 To 999999
powResult = BigInteger.Add(BigInteger.Add(BigInteger.Pow(i, 9), BigInteger.Pow(j, 9)), BigInteger.Pow(k, 9))
dResult = BigInteger.Subtract(Value, powResult)
If Len(dResult.ToString) <= 6 Then
a = i
b = j
c = k
d = dResult
RichTextBox1.Text = a & " , " & b & " , " & c & " , " & d
Exit For
Exit For
Exit For
End If
Next
Next
Next
End Sub
End Class
更新
我用vb寫了代碼。 但是用這段代碼,a是對的,b是對的但是c不對,結果不對。
a^9 + b^9 + c^9 + d 是一個比初始值大的數。
代碼應該帶來
一 = 217423
b= 78525
c = 3456
d= 215478
總價值可以= 1085912312763120759250776993188102125849391224162
但代碼帶來
一 = 217423
b= 78525
c=65957
d= 70333722607339201875244531009974
總值大於等於=1085935936469985777155428248430866412402362281319
我需要更改什么代碼才能使 c= 3456 和 d= 215478?
代碼是
導入 System.Numerics Public Class Form1 Private Function pow9(x As BigInteger) As BigInteger Dim y As BigInteger y = x * x ' x^2 y *= y ' x^4 y *= y ' x^8 y *= x ' x^9 返回 y 結束 Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim a, b, c, d, D2, n As BigInteger
Dim aa, bb, cc, dd, ae As BigInteger
D2 = BigInteger.Parse("1085912312763120759250776993188102125849391224162")
'first solution so a is maximal
d = D2
'a = BigIntegerSqrt(D2)
'RichTextBox1.Text = a.ToString
For a = 1 << ((Convert.ToInt32(Math.Ceiling(BigInteger.Log(d, 2))) + 8) / 9) To a > 0 Step -1
If (pow9(a) <= d) Then
d -= pow9(a)
Exit For
End If
Next
For b = 1 << ((Convert.ToInt32(Math.Ceiling(BigInteger.Log(d, 2))) + 8) / 9) To b > 0 Step -1
If (pow9(b) <= d) Then
d -= pow9(b)
Exit For
End If
Next
For c = 1 << ((Convert.ToInt32(Math.Ceiling(BigInteger.Log(d, 2))) + 8) / 9) To c > 0 Step -1
If (pow9(c) <= d) Then
d -= pow9(c)
Exit For
End If
Next
' minimize d
aa = a
bb = b
cc = c
dd = d
If (aa < 10) Then
ae = 0
Else
ae = aa - 10
End If
For a = aa - 1 To a > ae Step -1 'a goes down few iterations
d = D2 - pow9(a)
For n = 1 << ((Convert.ToInt32(Math.Ceiling(BigInteger.Log(d, 2))) + 8) / 9) To b < n 'b goes up
If (pow9(b) >= d) Then
b = b - 1
d -= pow9(b)
Exit For
End If
Next
For c = 1 << ((Convert.ToInt32(Math.Ceiling(BigInteger.Log(d, 2))) + 8) / 9) To c > 0 Step -1 'c must be search fully
If pow9(c) <= d Then
d -= pow9(c)
Exit For
End If
Next
If d < dd Then 'remember better solution
aa = a
bb = b
cc = c
dd = d
End If
If a < ae Then
Exit For
End If
Next
a = aa
b = bb
c = cc
d = dd
' a,b,c,d is the result
RichTextBox1.Text = D2.ToString
Dim Sum As BigInteger
Dim a9 As BigInteger
Dim b9 As BigInteger
Dim c9 As BigInteger
a9 = BigInteger.Pow(a, 9)
b9 = BigInteger.Pow(b, 9)
c9 = BigInteger.Pow(c, 9)
Sum = BigInteger.Add(BigInteger.Add(BigInteger.Add(a9, b9), c9), d)
RichTextBox2.Text = Sum.ToString
Dim Subst As BigInteger
Subst = BigInteger.Subtract(Sum, D2)
RichTextBox3.Text = Subst.ToString
End Sub
結束 Class
[更新]
下面的代碼試圖解決像 OP 這樣的問題,但我在閱讀它時犯了錯誤。
下面是1085912312763120759250776993188102125849391224162 = a^9+b^9+c^9+d^9+e
並最小化e
。
只是對 OP 的有趣難題過於興奮並且閱讀得太快。
我稍后再回顧這個。
OP的方法是O(N*N*N*N)
- 慢
下面是一個O(N*N*log(N))
的。
算法
讓 N = 1,000,000。 (看起來 250,000 足以滿足 OP 的總和 1.0859e48。)
定義 160+ 寬 integer 數學例程。
定義類型:pow9
int x,y,
int160least_t z
形成數組pow9 a[N*N]
填充x, y, x^9 + y^9
,對於 [1...N] 范圍內的每個x,y
。
在z
上對數組進行排序。
到目前為止的成本O(N*N*log(N)
。
對於索引為 [0... N*N/2] 的數組元素,對另一個數組元素進行二進制搜索,使得總和為 1085912312763120759250776993188102125849391224162
總和最接近的就是答案。
時間: O(N*N*log(N))
空間: O(N*N)
很容易從 FP 數學開始,然后通過 crafter 擴展 integer 數學得到更好的答案。
嘗試使用較小的N
和總和目標來解決實施問題。
如果a,b,c,d
可能為零,我想到了一個快速簡單的解決方案:
首先是比蠻力搜索a^9 + d = x
更好的東西,這樣a
是最大的(確保最小d
)......
讓d = 1085912312763120759250776993188102125849391224162
找到最大值a
使得a^9 <= d
這很簡單,因為我們知道 9 次方會將操作數的位寬乘以 9 倍,因此最大值最多可以是a <= 2^(log2(d)/9)
現在只需搜索從該數字開始的所有數字到零(遞減) 直到它的 9 次方小於或等於x
。 這個值將是我們a
。
它仍然是蠻力搜索,但是從更好的起點開始,因此需要更少的迭代。
我們還需要更新d
所以讓
d = d - a^9
現在只需以相同的方式找到b,c
(使用越來越小的余數d
)......這些搜索沒有嵌套,所以它們很快......
b^9 <= d; d-=b^9;
c^9 <= d; c-=b^9;
為了進一步提高速度,您可以通過平方使用功率對 9 次方進行硬編碼...
這將是我們的初始解決方案(在我的設置中,使用 32*8 位 uint 花費了約 200 毫秒),結果如下:
x = 1085912312763120759250776993188102125849391224162
1085912312763120759250776993188102125849391224162 (reference)
a = 217425
b = 65957
c = 22886
d = 39113777348346762582909125401671564
現在我們想要最小化d
所以簡單地遞減a
並向上搜索b
直到a^9 + b^9 <= d
仍然較低。 然后像以前一樣搜索c
並記住更好的解決方案。 a 應該向下搜索以在中間遇到b
但由於a
和b
具有相同的權力,只有少數迭代可能就足夠了(我使用了 50)從第一個解決方案(但我沒有證據證明這只是我的感覺)。 但是即使使用了全范圍,它的復雜性也比你的要低,因為我只有 2 個嵌套for
s 而不是你的 3,而且它們的范圍都較低......
這里是 C++ 的小例子(抱歉幾十年來沒有用 BASIC 編寫代碼):
//---------------------------------------------------------------------------
typedef uint<8> bigint;
//---------------------------------------------------------------------------
bigint pow9(bigint &x)
{
bigint y;
y=x*x; // x^2
y*=y; // x^4
y*=y; // x^8
y*=x; // x^9
return y;
}
//---------------------------------------------------------------------------
void compute()
{
bigint a,b,c,d,D,n;
bigint aa,bb,cc,dd,ae;
D="1085912312763120759250776993188102125849391224162";
// first solution so a is maximal
d=D;
for (a=1<<((d.bits()+8)/9);a>0;a--) if (pow9(a)<=d) break; d-=pow9(a);
for (b=1<<((d.bits()+8)/9);b>0;b--) if (pow9(b)<=d) break; d-=pow9(b);
for (c=1<<((d.bits()+8)/9);c>0;c--) if (pow9(c)<=d) break; d-=pow9(c);
// minimize d
aa=a; bb=b; cc=c; dd=d;
if (aa<50) ae=0; else ae=aa-50;
for (a=aa-1;a>ae;a--) // a goes down few iterations
{
d=D-pow9(a);
for (n=1<<((d.bits()+8)/9),b++;b<n;b++) if (pow9(b)>=d) break; b--; d-=pow9(b); // b goes up
for (c=1<<((d.bits()+8)/9);c>0;c--) if (pow9(c)<=d) break; d-=pow9(c); // c must be search fully
if (d<dd) // remember better solution
{
aa=a; bb=b; cc=c; dd=d;
}
}
a=aa; b=bb; c=cc; d=dd; // a,b,c,d is the result
}
//-------------------------------------------------------------------------
function bits()
僅返回占用的位數(類似於log2
但速度更快)。 這里最終結果:
x = 1085912312763120759250776993188102125849391224162
1085912312763120759250776993188102125849391224162 (reference)
a = 217423
b = 78525
c = 3456
d = 215478
它花了 1689.651 毫秒......正如你所看到的,這比你的快得多但是我不確定搜索迭代的次數,而微調a
是可以的,或者它應該按a/b
或什至整個范圍縮小到(a+b)/2
會比這慢很多...
最后一件事我沒有將 a,b,c 綁定到999999
所以如果你想要它你只需添加if (a>999999) a=999999;
任何a=1<<((d.bits()+8)/9)
... 之后的語句
[Edit1] 添加二進制搜索
好的,現在所有對第 9 根的完整搜索(除了a
的微調)都可以使用二進制搜索來完成,這將大大提高速度,同時忽略 bigint 乘法復雜性導致O(n.log(n))
對你的O(n^3)
... 這里更新了代碼(將完整迭代a
時間以使其安全):
//---------------------------------------------------------------------------
typedef uint<8> bigint;
//---------------------------------------------------------------------------
bigint pow9(bigint &x)
{
bigint y;
y=x*x; // x^2
y*=y; // x^4
y*=y; // x^8
y*=x; // x^9
return y;
}
//---------------------------------------------------------------------------
bigint binsearch_max_pow9(bigint &d) // return biggest x, where x^9 <= d, and lower d by x^9
{ // x = floor(d^(1/9)) , d = remainder
bigint m,x;
for (m=bigint(1)<<((d.bits()+8)/9),x=0;m.isnonzero();m>>=1)
{ x|=m; if (pow9(x)>d) x^=m; }
d-=pow9(x);
return x;
}
//---------------------------------------------------------------------------
void compute()
{
bigint a,b,c,d,D,n;
bigint aa,bb,cc,dd;
D="1085912312763120759250776993188102125849391224162";
// first solution so a is maximal
d=D;
a=binsearch_max_pow9(d);
b=binsearch_max_pow9(d);
c=binsearch_max_pow9(d);
// minimize d
aa=a; bb=b; cc=c; dd=d;
for (a=aa-1;a>=b;a--) // a goes down few iterations
{
d=D-pow9(a);
for (n=1<<((d.bits()+8)/9),b++;b<n;b++) if (pow9(b)>=d) break; b--; d-=pow9(b); // b goes up
c=binsearch_max_pow9(d);
if (d<dd) // remember better solution
{
aa=a; bb=b; cc=c; dd=d;
}
}
a=aa; b=bb; c=cc; d=dd; // a,b,c,d is the result
}
//-------------------------------------------------------------------------
function m.isnonzero()
與m!=0
相同,只是速度更快... 結果與上面的代碼相同,但a
的完整迭代的持續時間僅為821 ms
,如果使用之前的代碼,則為數千秒。
我認為除了使用一些多項式離散數學技巧我不知道只有一件事需要改進,那就是計算結果pow9
沒有乘法,這將大大提高速度(因為bigint 乘法是迄今為止最慢的操作)就像我在這里做了:
但我懶得推導它......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.