Question:
Solve:
这道题我多截了一张图,为什么呢? 《运行时间3s》
我是真的没想到,这直接暴力枚举abcd完全可以过,要是想玩点高级的也不是不行:
1. cd的枚举合并,具体操作就是循环的时候通过已经枚举出的abc去计算d,从而把第三层循环去掉
2. 提前去打表c和d的平方和,并将平方和与c的值一一对应的保存下来,然后去枚举a和b,利用a和b将cd平方和表示出来,将其与之前打表的结果比对,找到要输出的结果,参考第二段代码
Code:
暴力(未优化):
#include <bits/stdc++.h>
using namespace std;
map<int, int>mp;
int n;
int main(void)
{
scanf("%d", &n);
for(int a = 0; a*a <= n/4; a++){
for(int b = a; a*a + b*b <= n/2; b++){
for(int c = b; a*a + b*b + c*c <= n; c++){
for(int d = c; a*a+b*b+c*c+d*d <= n; d++){
if(a*a+b*b+c*c+d*d == n) {
printf("%d %d %d %d", a, b, c, d);
return 0;
}
}
}
}
}
return 0;
}
暴力(优化后):
#include <bits/stdc++.h>
using namespace std;
map<int, int>mp;
int n;
int main(void)
{
scanf("%d", &n);
//枚举c、d平方和,将平方和数映射为c
for(int i = 0; i*i <= n/2; i++){
for(int j = i; i*i + j*j <= n; j++){
//平方和数已经出现过,直接跳过,保证映射的c是最小的
if(mp.find(i*i + j*j) != mp.end()) continue;
mp[i*i + j*j] = i;
}
}
//枚举a,b
for(int a = 0; a*a <= n/4; a++){
for(int b = a; a*a + b*b <= n/2; b++){
//推导c,d
int num = n - a*a - b*b;
if(mp.find(num) == mp.end()) continue;
int c = mp[num];
int d = int(sqrt(num-c*c));
printf("%d %d %d %d", a, b, c, d);
return 0;
}
}
}
注:两段代码在蓝桥OJ上跑都是6ms,可能测试数据太小,也看不出有什么差距