SDUT3141:Count(哈希)好题

题目:传送门

题目描述

You are given an integer array s[] and are asked to count how many positions a, b, c and d satisfy the condition: s[a] + s[b] + s[c] == s[d].
Note that a, b, c, and d do not need to be distinct.

输入

 The first line of input contains an integer T, indicates the cases.
Each of the next T blocks contains an integer n first (0< n ≤1000 ), the length of the array s[], following with n integers representing s[] (0≤ si≤10^6 ).

输出

 Output T lines each contains the answer required. You'd better use 'long long' instead of 'int'.

示例输入

4
4
0 0 0 0
2
1 3
4
1 10 100 111
1
3

示例输出

Case #1: 256
Case #2: 1
Case #3: 6
Case #4: 0

这题题意很简单,但是我比赛的时候没有做出来,当时看见几乎所有人都A了痛苦啊,就是一道简单哈希。

题意:给定一个序列,查找所有满足s[a]+s[b]+s[c]=s[d]abcd的组数,注意,不要求abcd都不同。

分析:n<=1000,很明显O(n^3)的算法是不可能过的。式子可以转化为s[a]+s[b]=s[d]-s[c],然后复杂度就变成了O(n^2),先枚举ab,再枚举cd即可,用数组离散化。注意,因为s[a]+s[b]肯定是>=0,所以可以剪枝掉所有的s[d]-s[c]<0的情况。

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
typedef long long ll;
using namespace std;
int n,a[1010],h[2000010];
ll sum;
int main()
{
    int T;
    scanf("%d",&T);
    for(int z=1;z<=T;z++)
    {
        scanf("%d",&n);
        sum=0;
        memset(h,0,sizeof(h));
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
                if(a[i]-a[j]>=0)
                h[a[i]-a[j]]++;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
               sum+=h[a[i]+a[j]];
        }
        printf("Case #%d: %lld\n",z,sum);
    }
    return 0;
}
 

 

 
posted @ 2015-03-10 20:18  人艰不拆_zmc  阅读(159)  评论(0编辑  收藏  举报