Programming thinking week4 homework B-four series

topic

ZJM has four series A, B, C, D, each series has n numbers. ZJM takes a number from each sequence, and he wants to know how many schemes make the sum of the four numbers zero.
When there are multiple identical numbers in a sequence, treat them as different numbers.

Input

The first row: n (representing the number of numbers in the sequence) (1≤n≤4000).
In the next n rows, the i-th row has four numbers, which represent the i-th number in the sequence A, B, C, D (the number does not exceed the 28th power of 2).

Output

The number of different combinations is output.

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

Ideas

If the numbers in ABCD are directly enumerated, the complexity is O (n ^ 4), and the complexity is too high. The idea is to calculate A + B + C + D = 0.
In order to reduce enumeration points and reduce complexity, you can enumerate A and B, and then enumerate C and D, the complexity is O (n ^ 2). The idea to do this is to calculate A + B =-(C + D).
First enumerate A and B, calculate the sum of A + B, and store it in the array e [], and make it an ordered array. Then enumerate C and D, and calculate how many times the opposite of C + D appears in e []. When calculating how many times the opposite occurs, the dichotomy is used.
When performing dichotomy, the left and right boundaries l and r respectively take the left and right boundaries of the array e []. When l <r, loop, take the value at mid = (l + r) / 2. Whether its left and right are also the value you are looking for, until you find all the points that meet its requirements, and return the number of points found; if it is smaller than the value you want, l is updated to mid + 1; if it is larger than the value you want, r is updated to mid-1.

Code

#include <cstdio>
#include <algorithm>
using namespace std;

int a[4005],b[4005],c[4005],d[4005],e[4000*4000+5];
int n;

int find(int x){
    int l=0,r=n*n,leftx=0,rightx=0;
    while(l<=r){
        int mid=(l+r)/2;
        if(e[mid]==x){
            while((mid+rightx)<n*n&&e[mid+rightx]==x){
                rightx++;
            }
            while((mid-leftx)>=0&&e[mid-leftx]==x){
                leftx++;
            }
            return leftx+rightx-1;
        }
        else if(e[mid]<x)
            l=mid+1;
        else if(e[mid]>x)
            r=mid-1;
    }
    return 0;
}

int main() {
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    }
    int k=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            e[k]=a[i]+b[j];
            k++;
        }
    }
    int sum=0;
    sort(e,e+n*n);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            sum+=find(-(c[i]+d[j]));
        }
    }
    printf("%d",sum);
    return 0;
}

Title link

Published 24 original articles · praised 2 · visits 435

Guess you like

Origin blog.csdn.net/weixin_43805228/article/details/104978161