藍橋杯 四平方和


 

題目:四平方和

 

看到這個題目,第一個思路就是:

  枚舉abcd的值,然后判斷它們的平方和是不是等於N。

我們可以分析一下abcd的枚舉范圍

  a : 0 ~ sqrt( 5000000 / 4 )

  b : 0 ~ sqrt( 5000000 / 3 )

  c : 0 ~ sqrt( 5000000 / 2 )

  d : 0 ~ sqrt( 5000000 )

  這樣abcd的需要枚舉的范圍大約都是1000~2000,總枚舉量是1012這個量級。而108這個量級的計算量大約用時1秒。所以1012這個計算量肯定會超時

 

 

 

超時我們就要想辦法優化。最先能想到一個優化的辦法——減少枚舉的變量。

思路2:

  枚舉a、b、c,然后判斷 N - a- b- c是不是完全平方數。

同理,先分析一下abc的枚舉范圍:

  a : 0 ~ sqrt( 5000000 / 4 )

  b : 0 ~ sqrt( 5000000 / 3 )

  c : 0 ~ sqrt( 5000000 / 2 )

  可以發現abc的枚舉范圍仍然是1000~2000之間,總的枚舉量大概在109量級。再加上判斷一個整數X是不是完全平方數(開根號取整得到Y,然后再判斷Y*Y是不是等於X即可)復雜度是O(1)。所以整個算法的復雜度是O(N1.5),還是會超時

 

 

 

還超時,說明我們還要繼續優化。

思路3:

  只枚舉a、b,把余下的部分記作R,即 R = N - a- b2

於是我們的問題變成:c+ d= R 有沒有解?如果有解,其中c最小的解是什么?由於題目要求是abcd聯合主鍵升序第一的解。所以這里要快速求出來c最小的解。比如這時R = 25,那么得到的解應該是 c = 0, d = 5,而不是 c = 3,d = 4。這里哈希表就派上用場了。我們可以預先求出來 R = c+ d的解,用 unordered_map<int, int> f 來保存一個R對應的c。比如f[5]=1,表示R=5的解是 c = 1,(d=2可以由R和c算出來)。我們可以求出f[0], f[1], … f[5000000]的值,通過查哈希表用O(1)復雜度找到R = c+ d的解,這樣就更進一步優化了。

 

代碼如下:

 1 #include <cmath>
 2 #include <iostream>
 3 #include <unordered_map>
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     int n;
 9     unordered_map<int, int> f;
10     
11     cin >> n;
12     //預處理,求取 R = c2 + d2 的解並保存在unordered_map
13     for(int c = 0; c * c * 2 <= n; c ++ )
14         for(int d = c; c * c + d * d <= n; d ++)
15             if(f.find( c * c + d * d ) == f.end())    //在f中不存在則保存
16                 f[c * c + d * d] = c;
17     
18     for(int a = 0; a * a * 4 <= n; a ++)
19         for(int b = a; a * a + b * b <= n / 2; a ++)
20             if(f.find(n - a * a - b * b) != f.end())    //查哈希表,有解的話,計算並輸出 
21             {
22                 int c = f[n - a * a - b * b];
23                 int d = int(sqrt(n - a * a - b * b - c * c) + 1e-3);
24                 cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
25                 return 0;
26             }
27     
28     return 0;
29 } 
 
注:代碼中 1e-3 的作用:
  sqrt的返回值是浮點數,會有精度誤差。結果有可能出現比實際值略小的情況,比如sqrt(25)=4.999999999。而int強制類型轉換是向下取整,int(4.9999999999)=4。這樣就會由於精度誤差誤判25不是完全平方數。所以我給sqrt的結果加上了一個很小的浮點數,1e-3, 1e-6都可以,為了是把4.9999999這樣的數變成5.00099999 這樣int取整之后仍然是5。當然也可以不加。
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM