第七屆藍橋杯JavaB組-四平方和
阿新 • • 發佈:2019-01-29
四平方和
四平方和定理,又稱為拉格朗日定理:
每個正整數都可以表示為至多4個正整數的平方和。
如果把0包括進去,就正好可以表示為4個數的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符號表示乘方的意思)
對於一個給定的正整數,可能存在多種平方和的表示法。
要求你對4個數排序:
0 <= a <= b <= c <= d
並對所有的可能表示法按 a,b,c,d 為聯合主鍵升序排列,最後輸出第一個表示法
程式輸入為一個正整數N (N<5000000)
要求輸出4個非負整數,按從小到大排序,中間用空格分開
例如,輸入:
5
則程式應該輸出:
0 0 1 2
再例如,輸入:
12
則程式應該輸出:
0 2 2 2
再例如,輸入:
773535
則程式應該輸出:
1 1 267 838
資源約定:
峰值記憶體消耗(含虛擬機器) < 256M
CPU消耗 < 3000ms
四平方和定理,又稱為拉格朗日定理:
每個正整數都可以表示為至多4個正整數的平方和。
如果把0包括進去,就正好可以表示為4個數的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符號表示乘方的意思)
對於一個給定的正整數,可能存在多種平方和的表示法。
要求你對4個數排序:
0 <= a <= b <= c <= d
並對所有的可能表示法按 a,b,c,d 為聯合主鍵升序排列,最後輸出第一個表示法
程式輸入為一個正整數N (N<5000000)
要求輸出4個非負整數,按從小到大排序,中間用空格分開
例如,輸入:
5
則程式應該輸出:
0 0 1 2
再例如,輸入:
12
則程式應該輸出:
0 2 2 2
再例如,輸入:
773535
則程式應該輸出:
1 1 267 838
資源約定:
峰值記憶體消耗(含虛擬機器) < 256M
CPU消耗 < 3000ms
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Arrays; public class Main{ public static long []temp = new long[4]; public static long []ans = new long[4]; /** * 儲存按照升序排列的第一個答案;邏輯上篩選的規則是:如果ans小於temp中的,表示ans中儲存的就是滿足條件的,直接return; * 如果ans大於temp則temp中儲存的才是最適合的,則交換。 * 如果相等則進行下一次比較; * */ public static void saveAns(boolean flag){ //如果是第一個temp直接賦值給ans即可 if(flag) { for(int j = 0; j < temp.length; ++j) ans[j] = temp[j]; } for(int i = 0; i < 4; ++i) { if(ans[i] < temp[i]) return; else if(ans[i] > temp[i]) { for(int j = 0; j < temp.length; ++j) ans[j] = temp[j]; return; } } } /** * 總的思路是: * 從這個數num的開根號後得到的數num_sqrt開始遍歷: * 比如:num = 18, i = num_sqrt = 4; * 4 * 4 = 16,小於18則儲存4,num-16後還剩2,故只需從4遍歷到0,看那個數的平方不會超過2即可; * 4 * 4 = 16,大於2,進行下一次 * 3 * 3 = 9,大於2,進行下一次 * 2 * 2 = 4, 大於2,進行下一次 * 1 * 1 = 1,小於2,num - 1 = 1, 此時還要繼續判斷1是否滿足,1 * 1 = 1,小於等於1,num - 1 = 0; * 此時再呼叫saveAns()判斷該temp中的解是不是需要的解。 * * 然後i--, i = 3; * 3 * 3 = 9, 小於18,儲存3,num - 9 = 9,繼續判斷3 * 3 = 9, 9 - 9 = 0,就會跳出while,呼叫saveAns()方法。 * * 思路就是從後向前遍歷,先看最大的是否滿足,不滿足就找下一個,滿足就存到temp中。 * * 看不懂我寫的文字的話,可以自己在紙上把這個測試用例跑一下! * 如果那裡有錯的話,或者改進的地方請大家在留言區留言。THANKS * */ public static void main(String[] args) throws Exception{ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); long num = Long.parseLong(in.readLine()); in.close(); boolean flag = true; Arrays.fill(ans, 0L); long renum = 0, num_sqrt = (long)Math.sqrt(num); for(long i = num_sqrt; i >= 0; --i) { if(num == i * i) { ans[3] = i; break; } Arrays.fill(temp, 0L); renum = num; int temp_pos = 3; for(long j = i; temp_pos >=0 && j >= 0; --j) { while(temp_pos >= 0 && renum !=0 && (renum - j * j) >= 0) { renum -= j * j; temp[temp_pos--] = j; } if(0 == renum) { saveAns(flag); if(flag) flag = false; break; } } } for(int i = 0; i < ans.length; ++i) if(i == ans.length - 1) System.out.println(ans[i]); else System.out.print(ans[i] + " "); } }