1. 程式人生 > >四平方和解題報告---窮舉

四平方和解題報告---窮舉

                                              四平方和


四平方和定理,又稱為拉格朗日定理:
每個正整數都可以表示為至多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

思路:提前窮舉出兩個數的平方和能組成的數,然後用三個for迴圈實現

時間複雜度:O(n^2)

可能經驗不足吧...竟然蠢到用了4個for迴圈(下次做題記得帶腦子...)

AC Code:

#include <cstdio>
#include <cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int n;
bool vv[5000005];

void init(){
    memset(vv, false, sizeof(vv));  
    for(int i = 0; i * i <= n; i++){
        for(int j = 0; j * j <= n; j++){
            vv[i * i + j * j] = true;   //兩個數的平方能夠組成的數
        }
    }
}

int main(){
    while(scanf("%d", &n) != EOF){
        int len = sqrt(n);
        init();
        bool flag = true;
        for(int i = 0; i <= len && flag; i++){
            for(int j = i; j <= len && flag; j++){
                if(!vv[n - i * i - j * j]) continue;
                for(int k = j; k <= len && flag; k++){
                    double t = sqrt(n - i * i - j * j - k * k);
                    if(t == (int)t){
                        flag = false;
                        printf("%d %d %d %d\n", i, j, k, (int)t);
                        break;
                    }
                }
            }
        }
    }
	return 0;
}

這種方法也可以:O(n^3)

#include <cstdio>
#include <cmath>
#include<algorithm>
#include<iostream>
using namespace std;
int n;
int main(){
    while(scanf("%d", &n) != EOF){
        int len = sqrt(n);
        bool flag = true;
        for(int i = 0; i <= len && flag; i++){
            for(int j = i; j <= len && flag; j++){
                for(int k = j; k <= len && flag; k++){
                    double t = sqrt(n - i * i - j * j - k * k);
                    if(t == (int)t){
                        flag = false;
                        printf("%d %d %d %d\n", i, j, k, (int)t);
                        break;
                    }
                }
            }
        }
    }
	return 0;
}