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