题目
Description
小A一直认为,如果在一个由N个整数组成的数列An中,存在Am + An + Ap = Ai(1 <= m, n, p < i)(m, n, p可以相同)的话,Ai就是一个“好元素”。现在,小A有一个数列,他想知道这个数列中有多少个“好元素”,请你帮帮他。
Input
第一行只有一个正整数N,意义如上。
第二行包含N个整数,表示数列An。
Output
输出一个整数,表示这个数列中“好元素”的个数。
解题思路
在思路方面可以借鉴方程的解数。
10% n^4 随便做。
40% n^3 用布尔数组保存存在的元素,用三层枚举a[i],a[j],a[k],如果a[i]+a[j]+a[k]存在,那么答案加1。注意枚举顺序和判重。
70% n^2 预处理两个数的和,再枚举,因为每一个元素值比较小,开一个数组来存储是否存在。(其实n^3的方法加上剪枝也可以过)
100% n^2 因为元素的值比较大,在70%的思想上用哈希进行判断即可。
将原式移项得 ,每次将 放入 中,然后逐个判断 是否存在(注意判重和处理 的情况)。
代码
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
#include<cstdio>
#define hash(x) (x%inn+inn)%inn;
using namespace std;
const int inn=25000003;
int n,ans,ok,a[10005],h[inn];
int find(int x) //查询hash(x)的位置
{
int g=hash(x);
while (h[g]&&h[g]!=x) {
g++; if (g>inn) g=1;
}
return g;
}
void pus(int x)
{ if (!x) {ok=true; return;} h[find(x)]=x; return;}
bool check(int x)
{ if (!x) return ok; return h[find(x)]==x;}
int main()
{
//fre(good);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
for (int j=1;j<i;j++) pus(a[i-1]+a[j]);
for (int j=1;j<i;j++)
if (check(a[i]-a[j])) {ans++; break;}
}
printf("%d",ans);
}