四个数列
题目:
ZJM 有四个数列 A,B,C,D,每个数列都有 n 个数字。ZJM 从每个数列中各取出一个数,他想知道有多少种方案使得 4 个数的和为 0。
当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。
请你帮帮他吧!
Input:
第一行:n(代表数列中数字的个数) (1≤n≤4000)
接下来的 n 行中,第 i 行有四个数字,分别表示数列 A,B,C,D 中的第 i 个数字(数字不超过 2 的 28 次方)
Output:
输出不同组合的个数。
Example:
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
Output:
5
Hint:
样例解释: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
我的解题思路:
根据题意,要求我们对于四个数列,从每个数列中选一个数,四个数加在一起,和为0。如果遍历四个数组,则复杂度太高,所以可以两两计算。计算A+B的值,然后在计算C+D的值的过程中,找在A+B值中的相反数个数,最后统计所有的要求数对个数,即可。
我的总结:
要时刻考虑复杂度。
我的代码:
#include<iostream>
#include<algorithm>
using namespace std;
long long A[4000],B[4000],C[4000],D[4000],ans,N,ANS[16000000],ind=0,temp;
int bifind(int num)
{
int l=0,r=ind-1,ans1=-1,ans2=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(ANS[mid]==num)
{
ans1=mid;
l=mid+1;
}
else if(ANS[mid]>num) r=mid-1;
else l=mid+1;
}
l=0,r=ind-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(ANS[mid]>=num)
{
ans2=mid;
r=mid-1;
}
else l=mid+1;
}
if(ans1==-1||ans2==-1) return 0;
else return ans1-ans2+1;
}
int main()
{
cin>>N;
for (int i=0;i<N;i++)
{
cin>>A[i]>>B[i]>>C[i]>>D[i];
}
for(int i=0;i<N;i++)
{
for (int k=0;k<N;k++)
{
ANS[ind++]=A[i]+B[k];
}
}
sort(ANS,ANS+ind);
for (int i=0;i<N;i++)
{
for (int k=0;k<N;k++)
{
temp=C[i]+D[k];
ans+=bifind(-temp);
}
}
cout<<ans;
return 0;
}