题目大意
输入一个正整数N,接下来的N行每行输入4个数,从左到右分别是a,b,c,d。要求在N*4的
表中满足a+b+c+d=0条件的个数。N<=4000。
思路
需要转换一下思维,因为直接暴力遍历时N^4,可以分别遍历a+b和c+d的值,并且之存a+b的值,都存的话没必要而且浪费空间。之后算c+d时通过再来查找有多少a+b的值满足条件。
二分查找法:
首先将a+b的值sort一下,然后对于每一个c+d(之后算出来的),通过二分查找(也可以采用upper_bound和lower_bound)来确定满足条件的个数。最省空间,速度最慢,代码量最少,不过需要对细节进行处理。
Hash:
将a+b的值构建一个Hash表。然后对于每一个c+d的值只要O(1)的查询速度(平均来看)比二分法快10倍,速度最快,空间消耗最大,代码量较大。
Unorder_map:利用STL构建一个类似Hash表的数据结构,原理与Hash表类似,速度比二分法稍快一点,空间消耗是动态的,但是与Hash无太大区别(尤其是数据量极大时),但是最容易写。
上方的是unorder_map,下方是Hash。
代码(Hash)
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=4005;
int num[MAXN][4];
const int HashNum=2e7+3;
int HashOrd[HashNum];
int HashTable[HashNum];
void insert_Hash(int k){
int h=(k%HashNum+HashNum)%HashNum;
while(HashOrd[h]&&HashTable[h]!=k){
h++;
if(h>HashNum)h-=HashNum;
}
if(!HashOrd[h]){
HashOrd[h]=1;
HashTable[h]=k;
}
else HashOrd[h]++;
}
int Look_Table(int k){
int h=(k%HashNum+HashNum)%HashNum;
while(HashOrd[h]&&HashTable[h]!=k){
h++;
if(h>HashNum)h-=HashNum;
}
return HashOrd[h];
}
int main()
{
int n,T;
int a,b,c,d;
scanf("%d",&n);
bool ok=0;
while(n--){
memset(HashOrd,0,sizeof(HashOrd));
memset(HashTable,0,sizeof(HashTable));
scanf("%d",&T);
for(int i=1;i<=T;i++){
scanf("%d%d%d%d",&num[i][0],&num[i][1],&num[i][2],&num[i][3]);
}
for(int i=1;i<=T;i++){
for(int j=1;j<=T;j++){
insert_Hash(num[i][0]+num[j][1]);
}
}
long long int ans=0;
for(int i=1;i<=T;i++){
for(int j=1;j<=T;j++){
ans+=Look_Table(-num[i][2]-num[j][3]);
}
}
if(ok)printf("\n");
if(!ok)ok=1;
printf("%lld\n",ans);
}
}
代码(unorder_map)
#include<cstdio>
#include<unordered_map>
using namespace std;
const int MAXN=4005;
int box[MAXN][4];
unordered_map<int,int> Hash;
int main()
{
int t,n;
scanf("%d",&t);
bool ok=0;
while(t--){
scanf("%d",&n);
Hash.clear();
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&box[i][0],&box[i][1],&box[i][2],&box[i][3]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
Hash[box[i][0]+box[j][1]]++;
}
}
long long int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans+=Hash[-box[i][2]-box[j][3]];
}
}
if(ok)printf("\n");
ok=1;
printf("%lld\n",ans);
}
}