1. 程式人生 > >四平方和----藍橋杯軟體程式設計

四平方和----藍橋杯軟體程式設計

四平方和

四平方和定理,又稱為拉格朗日定理。每個整數都能表示為至多4個數的平方和。
如果把0算進去,就正好可以表示為4個數的平方和。
對於給定的一個正整數,可能存在多種平方和的表示方法。要求你對4個數進行排序
:0<=a<=b<=c<=d,並對所有的可能表示法按a,b,c,d為聯合主鍵升序排列,最後輸出
第一個表示法。
程式輸入為一個整數N(N<5 000 000),要求輸出4個非負整數,按從小到大排列,
中間用空格分開。
例如,輸入773535
輸出 1 1 267 838

思路:用一個數組a來存放a b c d, 用遞迴將每一位的數字填進去,個人感覺遞迴出口我已經用了一種比較好的方式。
另外,根據題目要求,0<=a<=b<=c<=d,並對所有的可能表示法按a,b,c,d為聯合主鍵升序排列,最後輸出第一個表示法,所以我們只求出第一個滿足條件的結果然後退出就行了。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void fun(int,int,int*);
void print();
void init();

int a[4];           //儲存4個數
int num[2237];      //預先儲存好0~2236的平方,方便計算

int main(int argc, char *argv[])
{
    int n;
    init();
    scanf("%d",&n);
    //printf("%f",sqrt(n));
fun(n,0,a); //print(); return 0; } //列印結果 void print() { int i; for(i=0;i<=3;i++) { printf("%d ",a[i]); } printf("\n"); } //初始化 void init() { int i; for(i=0;i<2237;i++) { num[i]=i*i; } } // void fun(int n,int i,int *p) { int m; m=(int
)sqrt(n); //a陣列滿了,則判斷是否符合條件 if(p == &a[3])//if((p-1) == &a[3]) { //if(n==0) if(num[m]==n && m>=i)//最後一個數n是一個平方數,那麼就滿足條件,這樣比之前那種方法減少了一層,速度提高很多 { *p=m; print(); exit(-1); //為了只打印第一次的資料新增的,如果要都儲存,可以在這裡進行修改儲存 } return ; } for(;i<=m;i++) { //if(num[i]<=n) //i^2 <= n,並不需要判斷,因為m=(int)sqrt(n) { *p=i; fun(n-num[i],i,p+1); //這裡不需要進行回溯了 } //else // break; } }

PS: 我上面的程式碼中有很多沒有用的程式碼,我並沒有刪除。其原因是,給自己提個醒,也給大家提個醒,將一個程式寫完後,效果達到了,結果也求出來了,但是這並不意味著結束。仍然需要繼續看看有沒有可以優化的地方。
尤其是我上面判斷遞迴出口的時候程式碼段,本來如果用被註釋掉的那段程式碼的話,求結果的時間會大大延長。其原因也不難想到,遞迴層數越多,分支越多,如果減少一層,其效率將是非常大的提高。
最後,我目前其實並不會那麼那麼多的套路,所以,程式碼可能不夠規範,不太容易理解,如果某位路過的大神也好,小神也罷,看出了我的程式中有可以改進的地方,歡迎在下方評論區提出。