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