题意: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;
}