我試圖寫C中的算法,該算法對於給定的自然數n
會發現對(x,y)
其中x,y
是整數的數目,使得找到所有的對,使得x^2 + Y^2 = <N^2
X + Y < = N
我能夠用兩個for循環要做到這一點,但是,這似乎是次優。對這個問題最有效的方法是什麼?
我試圖寫C中的算法,該算法對於給定的自然數n
會發現對(x,y)
其中x,y
是整數的數目,使得找到所有的對,使得x^2 + Y^2 = <N^2
X + Y < = N
我能夠用兩個for循環要做到這一點,但是,這似乎是次優。對這個問題最有效的方法是什麼?
只需要找到邊界處的點,即對於每個給定的x,最大的y_max s.t. x^2 + y_max^2 < = n。那麼給定x的有趣對的數量是2 * y_max + 1。對於x = 0,我們有y_max = n。對於x> 0,我們還必須考慮具有-x的對。這導致下面的代碼:
int pairCnt = 2*n+1; /* pairs (0,-n), (0,-n+1), ..., (0,n) */
int n2 = n*n;
for (int x=1; x<=n; ++x)
{
int y_max = (int)sqrt(n2-x*x);
pairCnt += 2*(2*y_max+1); /* (+/-x,-y_max), ..., (+/-x,y_max) */
}
使用SQRT的可以用下列的算法來避免:
int pairCnt = 2*n+1; /* pairs (0,-n), (0,-n+1), ..., (0,n) */
int n2 = n*n;
for (int x=1, y_max=n; 1; ++x)
{
if (y_max*y_max > n2-x*x)
--y_max;
if (x > y_max) break;
pairCnt += 2*(2*y_max+1); /* (+/-x,-y_max), ..., (+/-x,y_max) */
}
int s = 2*x-1; /* side length of maximal inscribed square */
pairCnt = 2*pairCnt - s*s;
用於第二算法的第一個想法是,當x增加Y_MAX將最大限度通過減少1,只要y_max> x(即我們沿半徑爲n的圓的內部從(0,n)直到我們穿過第一個中值y = x)。當我們添加一個以90°爲單位的計數點的副本(即迄今爲止發現的點數的兩倍)時,我們將對最大內切方格內的點進行兩次計數。
下面是n = 3的一種可視化。 *
將標記對置於有趣集合之外(x*x+y*y > n*n=9
)。數字標記了有趣集合(x*x+y*y <= n*n=9
)內的對的頻率到目前爲止。
before loop after loop after doubling result
---- ---- ---- ----
4321
4 ********* ********* ********* *********
3 ****1**** ****1**** ****1**** ****1****
2 **00100** **11111** **22222** **11111**
1 **00100** **11111** **22222** **11111**
0 *0001000* *0111110* *1222221* *1111111*
-1 **00100** **11111** **22222** **11111**
-2 **00100** **11111** **22222** **11111**
-3 ****1**** ****1**** ****1**** ****1****
-4 ********* ********* ********* *********
我會說「對」是指有序對,所以(0,1)不同於(1,0)。我認爲如果pair指向無序對{x,y},那麼它確實計數兩次。 –
好的,如果這些配對是有序的,那麼(0,1)和(1,0)就算爲2個解。 – chqrlie
嗯,但是等一下,(i,i)和0
如果你實現一個函數int int_sqrt (int n)
,它返回sqrt(double n)
的整數部分,那麼你可以通過使用這個函數只用一個循環來處理它。但整數平方根只存在於C++,所以你必須通過強制轉換結果,以實現一個在C int
編輯: 這裏的想法:
int x=0,result=0;
while ((n-(x*x)) >=0){
result += int_sqrt (n-(x*x)) +1;
x++;
}
這是在你接受所有的情況下,整數,包括0,使你的夫婦。
計算沒有重複的解決方案數量有點棘手,但我同意一個單一的循環就足夠了。 – chqrlie
取決於如果(x,y)被認爲不同於(y,x),其中x!= y,這是數學標準的情況;但是無論如何,這都會提示。 –
構造「我能夠用兩個for循環」代碼將有助於澄清這個廣泛的問題的細節。 – chux
如果內循環從'0'而不是'x'開始,那肯定是次優的。 –
@WeatherVane:正確,但它不會改變時間複雜度。 – chqrlie