4 Values whose Sum is 0 [POJ 2785]
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
input
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228 ) that belong respectively to A, B, C and D .
output
For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input | Sample Output |
---|---|
6 -45 22 42 -16 -41 -27 56 30 -36 53 -37 77 -36 30 -75 -46 26 -38 -10 62 -32 -54 -6 45 | 5 |
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
题意:给出n行数据,每行4列,现在每列中选择一个位置,使选择的四个位置上的数字和为0,问有多少种选择方法。(如果一列中有重复的数字,选择不同位置上的相同数字各算不同情况)
样例有六种选择方法: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
思路:如果一列一列地枚举复杂度是O(n4),可以考虑先把第一列和第二列合并起来,合并的结果是第一列和第二列的数字两两相加,一共有n2项,因为n<=4000,所以可以存在数组里。然后对第三列和第四列也用同样的办法合并,逐一在第一列与第二列合并的数组中查找与他大小相等符号相反的数,把答案累加起来。
#include<iostream>
#include<algorithm>
using namespace std ;
#define ll long long
const ll N = 5000 ;
ll a[ N ] , b[ N ] , c[ N ] , d[ N ] , n ;
ll ab[ N*N ] , cd[ N*N ];
int main(){
while( cin >> n ){
ll ans = 0 ;
for( int i = 1 ; i <= n ; i ++ ) cin >> a[ i ] >> b[ i ] >> c[ i ] >> d[ i ] ;
//合并ab
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= n ; j ++ )
ab[ (i-1)*n + j ] = a[ i ] + b[ j ] ;
//合并bc
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= n ; j ++ )
cd[ (i-1)*n + j ] = c[ i ] + d[ j ] ;
sort( ab+1 , ab+1+n*n ) ;
for( int i = 1 ; i <= n*n ; i ++ ){
ll pos1 , pos2 ;
pos1 = lower_bound( ab+1 , ab+1+n*n , -cd[i] ) - ab ;
pos2 = upper_bound( ab+1 , ab+1+n*n , -cd[i] ) - ab ;
ll num ;
//找-bc[i]在ab中出现的次数
if( ab[pos1] == -cd[i] && ab[pos2-1] == -cd[i] ) num = pos2 - pos1 ;
else num = 0 ;
ans += num ;
}
cout << ans << "\n" ;
}
return 0 ;
}