暴力求解
#include<iostream> #include<cmath> using namespace std; int n; int main() { scanf("%d",&n); for(int a=0;a*a<=n;a++) for(int b=a;b*b+a*a<=n;b++) for(int c=b;c*c+b*b+a*a<=n;c++) { int t=n-c*c-b*b-a*a; int d=sqrt(t); if(d*d==t) { printf("%d %d %d %d\n",a,b,c,d); return 0; } } }
二分
//先将 c^2+d^2 按字典序存储在结构体中 //然后枚举 a b 看差值是否在 c^2+d^2种找到 //二分法来查找 #include<iostream> #include<cmath> #include<algorithm> using namespace std; const int N=2500010; int n,m; struct Sum{ int s,c,d; }sum[N]; bool cmp(Sum s1,Sum s2) { if(s1.s!=s2.s) return s1.s<s2.s; else if(s1.c!=s2.c) return s1.c<s2.c; return s1.d<s2.d; } int main() { int n; cin>>n; for(int c=0;c*c<=n;c++) for(int d=c;c*c+d*d<=n;d++) sum[m++]={c*c+d*d,c,d};//枚举 c d 然后放入sum结构体中 c,d 按序排列 sort(sum,sum+m,cmp);//排序 for(int a=0;a*a<=n;a++) for(int b=a;a*a+b*b<=n;b++)//按序枚举 a b { int t=n-a*a-b*b;//求差值 int l=0,r=m-1;//结构体左右端点 while(l<r)//二分查找第一个>=t的值 { int mid=l+r>>1; if(sum[mid].s>=t) r=mid; else l=mid+1; } if(sum[l].s==t)//找到了 { printf("%d %d %d %d",a,b,sum[l].c,sum[l].d);//输出 return 0; } } }
哈希表
//先将 c^2+d^2 按字典序存储在结构体中 //然后枚举 a b 看差值是否在 c^2+d^2种找到 //哈希表来查找 实现O(1) #include<iostream> #include<cmath> #include<algorithm> #include<unordered_map>//哈希表 #define x first #define y second using namespace std; typedef pair<int,int> PII; const int N=2500010; int n,m; unordered_map<int,PII> S;//第一个int是"键" PII是"值" 通过键来查找值 int main() { int n; cin>>n; for(int c=0;c*c<=n;c++) for(int d=c;c*c+d*d<=n;d++) { int t=c*c+d*d; if(S.count(t)==0) S[t]={c,d}; //count 存在返回1 不存在返回0 //因为c d 本来就是从小到大枚举的 所以哈希表里存放的一定是最小的 } for(int a=0;a*a<=n;a++) for(int b=a;a*a+b*b<=n;b++)//按序枚举 a b { int t=n-a*a-b*b;//求差值 if(S.count(t)) { printf("%d %d %d %d\n",a,b,S[t].x,S[t].y); return 0; } } }