题目大意:
小A一直认为,如果在一个由N个整数组成的数列An中,存在Am + An + Ap = Ai(1 ≤m, n, p < i)(m, n, p可以相同)的话,Ai就是一个“好元素”。现在,小A有一个数列,他想知道这个数列中有多少个“好元素”,请你帮帮他。
思路:
这道题n≤5000,O(n3)过不了。
于是考虑移项,将a[k]移到等号左边,就成了
a[l]−a[k]=a[i]+a[j]
那么用哈希储存等号右边答案,再用等号左边去匹配,记录符合要求的数字个数即可。
时间复杂度:O(n2)
代码:
#include <cstdio> #include <algorithm> using namespace std; const int hash=25000004; const int csh=689207157; int n,a[10011],d[10011],m,sum,ha[hash]; bool ok; int locate(int x) //哈希 { int t=(x%hash+hash)%hash; int i=0; while (i<hash&&ha[(t+i)%hash]!=x&&ha[(t+i)%hash]!=csh) i++; return (t+i)%hash; } void inserts(int x) //插入元素至哈希表 { int y=locate(x); ha[y]=x; return; } bool find(int x) //在哈希表中查找元素 { return ha[locate(x)]==x; } int main() { freopen("good.in","r",stdin); freopen("good.out","w",stdout); scanf("%d",&n); for (int i=0;i<hash;i++) ha[i]=csh; for (int i=1;i<=n;i++) { scanf("%d",&a[i]); ok=false; for (int j=1;j<i;j++) //匹配 { if (find(a[i]-a[j])&&!ok) //存在这个数字且没有被匹配过 { sum++; //答案加一 ok=true; break; } } for (int j=1;j<=i;j++) inserts(a[i]+a[j]); //插入 } printf("%d\n",sum); }