4数之和为0(题解)

题意:ZJM 有四个数列 A,B,C,D,每个数列都有 n 个数字。ZJM 从每个数列中各取出一个数,他想知道有多少种方案使得 4 个数的和为 0。

当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。
思路
1.暴力枚举o(n^4)
2.两两枚举o(n^2),利用桶排
3.两两分组,一组求和排序(排序后可以用二分查找),另一组枚举求和sum,然后在上一组利用二分查找-sum的个数,时间复杂度比n^2高,但适应于桶排无法接受的数据范围(1e9)
总结:该题重要的是两两分组,求和处理,根据不同数据范围运用不同方法
反思:vector数组应用于数据范围较小时,当数据范围很大时静态数组比vector效率高。
代码:

//o(n^2)
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
vector<int>p[4];int mp[1000002];
int main()
 {  memset(mp,0,sizeoof(mp));
 	int n;cin>>n;
 	for(int i=0;i<4*n;i++)
 	{   int x;cin>>x;
 		p[i%4].push_back(x);
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
		  int sum=p[0][i]+p[1][j];
		  if(sum>=0)
		  mp[sum]++;
		  else mp1[-sum]++; 
		}
	}int ans=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			int sum=p[2][i]+p[3][j];
			if(sum<=0)
			ans=ans+mp[-sum];
			else  ans=ans+mp1[sum];
		}
	}  cout<<ans;
	return 0;
 }
//c++11支持unordered_map
//桶排
#include<iostream>
#include<vector>
#include<unordered_map>//c++11支持
using namespace std;
vector<int>p[4];
int main()
 { 
 	int n;cin>>n;unordered_map<int,int> mp;mp.clear();
 	for(int i=0;i<4*n;i++)
 	{   int x;cin>>x;
 		p[i%4].push_back(x);
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
		  int sum=p[0][i]+p[1][j];
		 mp[sum]++;
		}
	}long long ans=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			int sum=p[2][i]+p[3][j];
	       ans=ans+mp[-sum];
		}
	}  cout<<ans;
	return 0;
}
//二分查找个数
#include<iostream>
//#include<vector>    vector太不友好了,当数组很大时不要开,因为扩容需要时间!! 
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
vector<long long>p[4];
long long E[100000002];
int binary(long long num,int k)
{
	int l=0;int r=k-1;int ansl=-1;
	while(l<=r)
	{
		int mid=(l+r)/2;
		if(E[mid]==num)
		{
			ansl=mid;r=mid-1;
		}
		else if(E[mid]>num) r=mid-1;
		else l=mid+1;
	}
	int ll=0;int rr=k-1;int ansr=-1;
	while(ll<=rr)
	{
		int mid=(ll+rr)/2;
		if(E[mid]==num)
		{
			ansr=mid;ll=mid+1;
		}
		else if(E[mid]>num) rr=mid-1;
		else ll=mid+1;
	}
	if(ansr!=-1&&ansl!=-1)
	return ansr-ansl+1;
	return 0;
}
int main()
{
	int n;cin>>n;
 	for(int i=0;i<4*n;i++)
 	{   long long x;scanf("%lld",&x);
 		p[i%4].push_back(x);
	} int k=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
		  long long sum=p[0][i]+p[1][j];
		  
		  E[k++]=sum;
		}
	}
	sort(E,E+k);long long ans=0;	
    for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			long long sum=-(p[2][i]+p[3][j]);
		    ans=ans+binary(sum,k);  	
		}
	} cout<<ans;
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值