原题:
http://172.16.0.132/senior/#contest/show/1929/0
题目描述:
小A一直认为,如果在一个由N个整数组成的数列An中,存在Am + An + Ap = Ai(1 <= m, n, p < i)(m, n, p可以相同)的话,Ai就是一个“好元素”。现在,小A有一个数列,他想知道这个数列中有多少个“好元素”,请你帮帮他。
输入:
第一行只有一个正整数N,意义如上。
第二行包含N个整数,表示数列An。
输出:
输出一个整数,表示这个数列中“好元素”的个数。
样例输入:
输入1:
2
1 3
输入2:
6
1 2 3 5 7 10
输入3:
3
-1 2 0
样例输出:
输出1:
1
输出2:
4
输出3:
1
数据范围限制:
对于10%的数据 1<=N<=10
对于40%的数据 1<=N<=500 -10^5<=Ai<=10^5
对于70%的数据 1<=N<=5000 -10^6<=Ai<=10^6
对于100%的数据 1<=N<=5000 -10^9<=Ai<=10^9
分析:
好元素
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%的思想上用哈希进行判断即可。
实现:
const
id=14150547;
var
i,j,t,n,ans,k:longint;
bz:boolean;
sum:array[-id..id] of longint;
a:array[0..5001] of longint;
function hash(i:longint):longint;
var
j:longint;
begin
j:=i mod id;
while(sum[j]<>0)and(sum[j]<>i)do j:=(j+1) mod id;
exit(j);
end;
begin
assign(input,'good.in');reset(input);
assign(output,'good.out');rewrite(output);
readln(n);
for i:=1 to n do
begin
read(a[i]);
for j:=1 to i-1 do
begin
t:=a[i]-a[j];
if t=0 then
begin
if bz then
begin
inc(ans);
break;
end;
end
else
if sum[hash(t)]=t then
begin
inc(ans);
break;
end;
end;
if a[i]=0 then bz:=true;
for j:=1 to i do
sum[hash(a[i]+a[j])]:=a[i]+a[j];
end;
writeln(ans);
close(input);close(output);
end.