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 2 28 ) 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
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
Sample Output
5

Hint
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).

大致题意:给你四列数,让你从每一列中选一个数,使得4个数的和为0,问有多少种方案

思路:如果直接暴力枚举的话n^4肯定是会超时的,所以我们折半枚举,先暴力枚举出其中前两列的所有和,存到一个数组中,排个序。然后再枚举后两列的和,利用lower_bound可以快速找到所需对应的前两列的结果,时间复杂度差不多就降到了n^2.

代码如下

#include <cstdio>  
#include <cstring>  
#include <iostream> 
#include <algorithm>
#include <map>   
#define ll long long

using namespace std; 
ll s1[4005];
ll s2[4005];
ll s3[4005];
ll s4[4005];

ll sum1[16000005];
ll sum2[16000005];
int main() 
{ 
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld%lld%lld",&s1[i],&s2[i],&s3[i],&s4[i]);
    }
    int l=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        sum1[l++]=s1[i]+s2[j];
    }

    sort(sum1,sum1+n*n);

    ll sum=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        ll x=s3[i]+s4[j];
        x=-x;
        int tmp1=lower_bound(sum1,sum1+n*n,x)-sum1;//返回a[]中第一个大于等于val的位置
        int num=0;
        for(int k=tmp1;k<n*n;k++)//相同的值可能有多个
        {

            if(sum1[k]==x)
            {
                sum++;
            }
            else 
            break;
        }
    }
    printf("%lld",sum);
    return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值