452 四合归零

来源:互联网 发布:高中生学编程 编辑:程序博客网 时间:2024/06/08 07:36

F 四合归零

时间限制:1000ms   内存限制:131072kb

通过率:11/26 (42.31%)    正确率:11/96 (11.46%)

每份测试数据时限:1000ms

总时限:2000ms(共2份测试数据)

Problem Description

Magry最近看到了一个问题——

给定四个等长整数集合A,B,C,DA,B,C,D, 要求分别从中选取一个元素 a,b,c,da,b,c,d 使得 a+b+c+d=0a+b+c+d=0 成立。

问:有多少种选法?

乍一看这问题挺简单的,他觉得完成它是一件轻而易举的事。

可是一看这计算量,他被吓成一团了……

你们能帮帮他么QWQ

Input

多组测试数据(不超过5组),以EOF结尾。

每组测试数据第一行为一个正整数n,表示四个数组的长度。0<n40000<n≤4000

接下来4行,每行n个整数,各行分别是所给定 A,B,C,D 四个数组。各数组各元素取值范围为:500000x500000−500000≤x≤500000

Output

对于每组数据,输出一行,一个数,选择方法总数。

Sample Input

21 23 4-1 95-95 -4

Sample Output

2

Sample Explanation

很显然,样例当中只有 1+414=01+4−1−4=0 和 2+314=0

2+3−1−4=0 这两种情况成立。


解析:

首先很容易想到的是四重循环算法,时间复杂度为O(n^4),但这个算法显然会超时。

可以先枚举A、B两组数中元素的和,将结果存在数组然后再遍历C、D数组的和,累加答案即可。

代码:

#include <cstdio>#include <cstring>int a[4][4003], b[2000005];int main(){    int n, ans;    while (scanf("%d", &n)==1){        memset(b, 0, sizeof(b));        for (int i=0; i<4; i++){            for (int j=1; j<=n; j++) scanf("%d", &a[i][j]);        }        ans = 0;        for (int i=1; i<=n; i++)        for (int j=1; j<=n; j++){            b[a[0][i]+a[1][j]+1000000]++;        }        for (int i=1; i<=n; i++)        for (int j=1; j<=n; j++){            ans+=b[1000000-a[2][i]-a[3][j]];        }        printf("%d\n", ans);    }}