http://poj.org/problem?id=2549
维基百科有3Sum算法:https://en.wikipedia.org/wiki/3SUM
sort(S); for i=0 to n-3 do a = S[i]; k = i+1; l = n-1; while (k<l) do b = S[k]; c = S[l]; if (a+b+c == 0) then output a, b, c; // Continue search for all triplet combinations summing to zero. k = k + 1 l = l - 1 else if (a+b+c > 0) then l = l - 1; else k = k + 1; end end end
1、排序,求任意两个数的和;将和与(i,j)通过Hash数组做映射,处理hash冲突用图论中的邻接表---学数据结构的时候老师讲过的桶式哈希
2、枚举两数(p,q)之差,通过HASH找到(i,j),保证p,q,i,j都不等即可
40多ms
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdin) const int SIZE = 536870911; const int MOD = 9973; const int MAXN = 1000 + 100; ll s[MAXN]; struct Node { int i; int j; int next; }rec[1100005]; int Hash[1100005];//头结点 inline ll Abs(ll x) { return x>0?x:(-x); } int main() { //IN("poj2549.txt"); int n,cnt; while(~scanf("%d",&n) && n) { CL(Hash,0xff); for(int i=0;i<n;i++) scanf("%lld",&s[i]); sort(s,s+n); cnt=0; for(int i=0;i<n-1;i++) for(int j=i+1;j<n;j++) { rec[cnt].i=i; rec[cnt].j=j; ll sum=Abs(s[i]+s[j])%MOD; rec[cnt].next=Hash[sum]; Hash[sum]=cnt; cnt++; } int ok=0; ll ans=0; for(int i=n-1;i>0;i--) { if(ok)break; for(int j=0;j<i;j++) { if(ok)break; ll sum=Abs(s[i]-s[j])%MOD; for(int v=Hash[sum];v!=-1;v=rec[v].next) { int h=rec[v].i; int k=rec[v].j; if(s[h]+s[k]==s[i]-s[j] && rec[v].i!=i && rec[v].i!=j && rec[v].j!=j && rec[v].j!=i) { ok=1; ans=s[i]; break; } } } } if(ok)printf("%lld\n",ans); else printf("no solution\n"); } return 0; }