1. 程式人生 > >第七屆藍橋杯第8題:四平方和

第七屆藍橋杯第8題:四平方和

四平方和


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


請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。


注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。

提交時,注意選擇所期望的編譯器型別。

分析:直接窮舉:

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

int main()
{
	int a, b, c, n, flag = 0;
	double maxN, d;
	scanf("%d", &n);
	maxN = sqrt(n);

	for(a = 0; a <= maxN; a ++){
		for(b = a; b <= maxN; b ++){
			for(c = b; c <= maxN; c ++){
				d = sqrt(n - a*a - b*b - c*c);
				if(d == (int)d){
					printf("%d %d %d %d\n", a, b, c, (int)d);
					flag = 1;
					break;
				}
			}
			if(flag)
				break;
		}
		if(flag)
			break;
	}
	return 0;
}

大神程式碼:

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

int mpt[5000010] ={0};  //mpt[i] = 1表示i 能夠用兩個完全平方數相加而得。
int n;

void init()
{
	for(int i = 0 ; i*i <= n ; i ++)
		for(int j = 0 ; j*j <=n ; j ++)
			if(i*i+j*j <= n) mpt[i*i+j*j] = 1;
}

int main()
{
	int flag = false;
	scanf("%d",&n);
	init();
	for(int i = 0 ; i * i <= n ; i ++)
	{
		for(int j = 0 ; j * j <= n ; j ++){
			if(mpt[n - i*i - j*j] == 0)
				continue;   //如果剩下的差用兩個完全平方數不能組合出來就不繼續

			for(int k = 0 ; k * k <= n ; k ++)
			{
				int temp = n - i*i - j*j - k*k;
				double l = sqrt((double) temp);
				if(l == (int)l )
				{
					printf("%d %d %d %d\n",i,j,k,(int)l);
					flag = true;
					break;
				}
			}
			if(flag)break;
		}
		if(flag)break;
	}
	return 0;
}