问题:
ZJM 有四个数列 A,B,C,D,每个数列都有 n 个数字。ZJM 从每个数列中各取出一个数,他想知道有多少种方案使得 4 个数的和为 0。
当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。
请你帮帮他吧!
input:
第一行:n(代表数列中数字的个数) (1≤n≤4000)
接下来的 n 行中,第 i 行有四个数字,分别表示数列 A,B,C,D 中的第 i 个数字(数字不超过 2 的 28 次方)
output:
输出不同组合的个数。
sample input6
-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
题解:
这个题是考察我们对于二分的理解,在读到题时能够迅速想到对于一个大量数据的遍历处理转换为二分处理。四个数组,本来要n的四次方,先将其中ab,cd相加就变成两个数组,对cd进行二分处理,就变为nlogn的复杂度,大大节省了我们的时间。
完整代码:
#include <iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int a[4000];
int b[4000];
int c[4000];
int d[4000];
int ab[16000000];
int cd[16000000];
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
int n;
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
scanf("%d",&b[i]);
scanf("%d",&c[i]);
scanf("%d",&d[i]);
}
int count=0;
for(int i=0;i<n;i++) //对数组进行处理
{
for(int j=0;j<n;j++)
{
ab[count]=a[i]+b[j];
cd[count]=c[i]+d[j];
count++;
}
}
int size=count;
sort(cd,cd+count);
count=0;
for(int i=0;i<size;i++) //二分法寻找相对应的组
{
int l=0;
int r=size-1;
int mid;
while(l<r)
{
mid=(l+r)>>1;
if(ab[i]+cd[mid]>=0)
{
r=mid;
}
else
{
l=mid+1;
}
}
while(l<size&&ab[i]+cd[l]==0)
{
count++;
l++;
}
}
cout<<count<<endl;
return 0;
}
反思:
对于二分的应用要重复练习,包括每一次l,r的更改和判断条件,都是一些常犯的错误。