NWPU_四月月赛

MD,这场月赛知道的时候,只剩下不到一半的时间了,于是在比赛结束前,立马拿下3道签到题,还不算太渣。

C - A+B

Time Limit: 5000 ms        Memory Limit: 65536 KB

Submit

Description

有一个n个数的序列,每个数都是不同的,从这个序列中选出四个数问有多少个四元组满足a+b=c+d。

Input

输入第一行包含一个整数T,表示接下来有T组数据。(T<=10)

每一组数据有一个整数n(4<=n<=1000),表示总共有n个数。

接下来一行是n个数,保证每个数字都不同,数的大小0<x<=10^9。

Output

输出T组,每组数据一行,先输出“Case #t: ”。

接下来输出四元组的个数。

Sample Input

2
4
1 2 3 4
4
1 2 4 6

Sample Output

Case #1: 1
Case #2: 0

Hint

Huge input,scanf is recommended.

解题思路:

  这题拿到后的第一反应是POJ上那道折半搜索,就是说,给你4个长度相同的数组,让你每次只能从每个数组中取出来一个数字,使得这些数字的和加起来满足

  a[i]+b[j]+c[k]+d[l] == 0,当然,直接O(n4)就是作死,直接把这个等式划分成两部分,然后利用二分折半搜索就可了。

  关于这道题就比较水了,上来后O(n2)直接预处理相邻两项的和,然后线性扫一遍,把相同的个数拿出来做C(k,2)的组合数就是我们要的答案了

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 int a[1005],cnt[1000005];
 9 int main()
10 {
11     int T;
12     scanf("%d",&T);
13     for(int ca=1;ca<=T;ca++)
14     {
15         int n;
16         scanf("%d",&n);
17         for(int i=1;i<=n;i++)
18         {
19             scanf("%d",&a[i]);
20         }
21         int tot=0;
22         for(int i=1;i<=n;i++)
23         {
24             for(int j=i+1;j<=n;j++)
25             {
26                 cnt[tot++]=a[i]+a[j];
27             }
28         }
29         //printf("%d
",tot);
30         sort(cnt,cnt+tot);
31         int now=1;
32         long long ans=0;
33         for(int i=1;i<tot;i++)
34         {
35             if(cnt[i]==cnt[i-1])
36             {
37                 now++;
38             }
39             else
40             {
41                 ans+=now*(now-1)/2;
42                 now=1;
43             }
44         }
45         ans+=now*(now-1)/2;
46         printf("Case #%d: %lld
",ca,ans);
47     }
48     return 0;
49 }
原文地址:https://www.cnblogs.com/wikioibai/p/4461865.html