这道题虽说不难但是还是摩擦了半天。另外例题8-2感觉很神奇,就不放代码了
网上不少人用了数组排序的方法,也有自己实现hash_map的方法。我用了哈希,主要是为了练习练习自己写哈希
要注意一些对性能会造成影响的部位:
1、vector
vector中的元素多了之后,push_back的速度非常非常慢。数据量大的时候要避免vector
2、memset
在数据数量级在10^7左右的时候,开数组的时候最好算出一个比较精确的数组大小值。能不memset就不要memset,能少开数组就少开
3、STL map
虽然号称是O(logn),但是STL的map的复杂度有比较可观的常数项。毕竟要建红黑树,肯定比自己写二分查找要慢很多。
另外,题目似乎没说每个list中的元素互斥,所以对于每个sum其实还应该判断一下组成元素是否相同
比如下面的input
1
2
0 0 0 0
0 0 0 0
我的程序(包括网上很多人的)会输出16,但其实distinct的解只有一组(0,0,0,0)。我觉得可能UVa也不想让选手花太多时间在这种无聊的问题上
Run Time: 4.588s
#define UVa "LT8-3.1152.cpp"
char fileIn[30] = UVa, fileOut[30] = UVa;
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
//Global Variables. Reset upon Each Case!
const int hashsize = 10000000; //large(100000000) -> TLE small(10000)->TLE 83886080->ok
const int maxstate = 10000000;//4000*4000 + 10 -> 5s, 100000000 -> 8s;
int head[hashsize], next[maxstate], st[maxstate];
/
int hash(int a) {
return abs(a)%hashsize;
}
int try_to_insert(int p) {
int hashcode = hash(st[p]);
next[p] = head[hashcode];
head[hashcode] = p;
return 1;
}
int count(int a) {
int hashcode = hash(a);
int u = head[hashcode];
int cnt = 0;
while(u != -1) {
if(st[u] == a) cnt ++;
u = next[u];
}
return cnt;
}
int main() {
int kase;
scanf("%d", &kase);
for(int kk = 0; kk < kase; kk ++) {
if(kk) printf("\n");
int lists[4010][4];
memset(head, -1, sizeof(head));
memset(next, -1, sizeof(next));
int n, tmp;
scanf("%d", &n);
int counter = 0;
for(int i = 0; i < n; i ++) {
for(int j = 0; j < 4; j ++) {
scanf("%d",&lists[i][j]);
}
}
int p = 0;
for(int i = 0; i < n; i ++) {
for(int j = 0; j < n; j ++) {
int sum = lists[i][0] + lists[j][1];
st[p] = sum;
try_to_insert(p++);
}
}
int cnt = 0;
for(int i = 0; i < n; i ++) {
for(int j = 0; j < n; j ++) {
int sum = lists[i][2] + lists[j][3];
cnt += count(-sum);
}
}
printf("%d\n", cnt);
}
return 0;
}