[jzoj 3508]【NOIP2013模拟11.5B组】好元素 {哈希表}

题目

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%的思想上用哈希进行判断即可。

将原式移项得 a [ m ] + a [ n ] = a [ p ] a [ i ] ,每次将 a [ m ] + a [ n ] 放入 h a s h 中,然后逐个判断 h a s h ( a [ p ] a [ i ] ) 是否存在(注意判重和处理 h a s h [ 0 ] 的情况)。


代码

#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); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/81105189