jzoj3508NOIP2013模拟11.5B组DAY 1 (7.12)HASH好元素(good)

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj3508NOIP2013模拟11.5B组DAY 1 (7.12)HASH好元素(good)相关的知识,希望对你有一定的参考价值。


题面

【jzoj】【3508】【NOIP2013模拟11.5B组】好元素(good)

Description

小A一直认为,如果在一个由N个整数组成的数列An中,存在Am + An + Ap = Ai(1 <= m, n, p < i)(m, n, p可以相同)的话,Ai就是一个“好元素”。现在,小A有一个数列,他想知道这个数列中有多少个“好元素”,请你帮帮他。

Input

第一行只有一个正整数N,意义如上。

第二行包含N个整数,表示数列An。

Output

输出一个整数,表示这个数列中“好元素”的个数。

Sample Input

输入1:

2
1 3

输入2:

6
1 2 3 5 7 10

输入3:

3
-1 2 0

Sample Output

输出1:

1

输出2:

4

输出3:

1

Data Constraint

对于10%的数据 1<=N<=10

对于40%的数据 1<=N<=500 − 1 0 5 < = A i < = 1 0 5 -10^5<=Ai<=10^5 105<=Ai<=105

对于70%的数据 1<=N<=5000 − 1 0 6 < = A i < = 1 0 6 -10^6<=Ai<=10^6 106<=Ai<=106

对于100%的数据 1<=N<=5000 − 1 0 9 < = A i < = 1 0 9 -10^9<=Ai<=10^9 109<=Ai<=109


解题思路

先考虑 A m + A n + A p = A i A_m+A_n+A_p=A_i Am+An+Ap=Ai
搞三重循环枚举m,n,p,搞个桶统计可以组成的数,再枚举i,判断 A i A_i Ai可不可以组成

可以发现 A m + A n = A i − A p A_m+A_n=A_i-A_p Am+An=AiAp会更优
简单来说就是,两重循环 * 2(一个是求 A m + A n A_m+A_n Am+An,放进桶里,一个是求 A i − A p A_i-A_p AiAp存不存在)

− 1 0 9 < = A i < = 1 0 9 -10^9<=Ai<=10^9 109<=Ai<=109
∴ 要用hash当桶
hash板子题

tips
因为1 <= m, n, p < i
做i时,i-1的时候就已经把1 <=m, n< i(1 <=m, n<= i - 1)给放进hash里了


Code

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const long long Mod = 25000003;
int n, ans;
long long a[5100], hash[Mod + 100], now, P;

void HASH(long long x) {
	long long cnt = (x % Mod + Mod) % Mod, i = 0;
	while(i < Mod && hash[(cnt + i) % Mod] != P && hash[(cnt + i) % Mod] != x)
		i++;
	if(hash[(cnt + i) % Mod] == P)
		hash[(cnt + i) % Mod] = x;
}

int find(long long x) {
	long long cnt = (x % Mod + Mod) % Mod, i = 0;
	while(i < Mod && hash[(cnt + i) % Mod] != P && hash[(cnt + i) % Mod] != x)
		i++;
	return (hash[(cnt + i) % Mod] == x);
}

int main() {
//	freopen("good.in", "r", stdin);
//	freopen("good.out", "w", stdout);
	scanf("%d", &n);
	for(int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	memset(hash, -Mod, sizeof(hash));
	P = hash[1];
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j < i; j++)  //即p
			if(find(a[i] - a[j])) {  
				ans++;
				break;
			}
		for(int j = 1; j <= i; j++)  //即n
			HASH(a[i] + a[j]);  //tips  //因为m是1到n,和i相同且同步增长,所以直接用i循环替代m
	}
	printf("%d", ans);
}

以上是关于jzoj3508NOIP2013模拟11.5B组DAY 1 (7.12)HASH好元素(good)的主要内容,如果未能解决你的问题,请参考以下文章

jzoj3515NOIP2013模拟11.6B组二分DP软件公司

[jzoj]3506.NOIP2013模拟11.4A组善良的精灵(fairy)(深度优先生成树)

jzoj3505NOIP2013模拟11.4A组组合逆元积木

jzoj3523NOIP2013模拟11.7A组树上倍增JIH的玩偶(tree)

jzoj3528NOIP2013模拟11.7A组数学拓扑DP图书馆(library)

Jzoj4742NOIP2016提高A组模拟9.2快速幂单峰