完全平方:用一个整数乘以自己例如1*1,2*2,3*3等,依此类推。
完全平方数:若一个数能表示成某个整数的平方的形式,则称这个数为完全平方数。
四平方定理:任何一个整数都可以表示成不超过四个整数的平方之和;
题1:输入n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。且让组成和的完全平方数的个数最少。
解题思路:由四平方定理可以得出最多有4个,另外还有一个重要的定理:满足四数平方和定理的数n(这里要满足由四个完全数构成,小于四个不行),必定满足 ,所以如果n是四的倍数且n对8取余为7,则一定有4个完全平方数(可以重复)的和组成;剩下的再判断是3个,2个或者1个,其中1个或者2个比较好判断,剩下的就是3个的;
#include<iostream>
#include<algorithm>
using namespace std;
int get_num(int n){
while(n%4==0) n/= 4;
if(n%8 == 7) return 4;
for(int i = sqrt(n), i>0; --i){
int j = (int)(n-i*i);
if(i*i + j*j==n){
if(j) return 2;
else retuen 1;
}
}
return 3;
}
int main(){
int n;
while(cin>>n){
int num = get_num(n);
cout<<num<<endl;
}
return 0;
}
题2:在上面的基础上再加上要从小到大输出组成n的多个完全数,此时不要求重复如果没有则输出NA
思路:此时可分为3个部分,首先是将0~n对应的完全数保存在一个数组或者集合中,这里因为集合查找方便所以放在集合里;
然后是题1的方法,最后则对第一步得到的集合进行遍历找出所需的完全数并将其输出;
#include<set>
#include<iostream>
#include<vector>
using namespace std;
set<int> get_data(int n){//获取每个完全平方数
set<int> data;
for(int i = 0; i<n; ++i){
data.insert(i*i);
}
return data;
}
vector<int> get_out(set<int> data, int n, int m){
int p = m;
vector<int> out_o;
set<int> :: iterator it = data.lower_bound(n);
while(p--){
out_o.clear();
--it;
int s = 0,a, s1 = 0;
set<int> :: iterator it1 = it;
while(it1 != data.begin()){
a = *it1;
s += a;
if(s<n){
out_o.push_back(a);
--it1;
}
else if(s>n){
s -= a;
--it1;
}
else{
out_o.push_back(a);
break;
}
if(out_o.size()>m) break;
}
int len = out_o.size();
for(int i = 0; i<len; ++i)
s1+=out_o[i];
if(len == m && s1==n) break;
}
return out_o;
}
int main(){
int n;
while(cin>>n){
set<int> data = get_data(n);
int m = get_num(n);
vector<int> out_o = get_out(data, n, m);
int len = out_o.size(), s = 0;
for(int i = 0; i<len; ++i)
s += out_o[i];
if(s==n){
for(int i = len-1; i>=0; --i)
cout<<out_o[i]<<" ";
}
cout<<"NA";
cout<<endl;
}
return 0;
}