样例中符合条件的5种组合如下:
{-45 -27 42 30}
{26 30 -10 -46}
{-32 22 56 -46}
{-32 30 -75 77}
{-32 -54 56 30}
a+b+c+d=0,(a+b)=-(c+d) ,
就是预处理出a+b和c+d,然后二分找-(c+d)
(二分或者用stl的hash unordered_map优化,打开C++11用这个
#include
using namespace std;
typedef long long ll;
const int N=;
ll a[N],b[N];
unordered_map ma;
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=;i
for(i=;i
for(i=;i
for(j=;j
++ma[a[i]+b[j]];
for(i=;i
for(i=;i
ll ans=;
for(i=;i
for(j=;j
ans+=ma[-a[i]-b[j]];
printf("%lld\n",ans);
return ;
}
出题人的代码
#include
#include
#include
using namespace std;
#define MAX 4005
int a[MAX],b[MAX],c[MAX],d[MAX];
int cd[MAX*MAX];
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
int n,i,j;
cin>>n;
for(i=;i
for(i=;i
for(i=;i
for(i=;i
for(i=;i
for(j=;j
cd[n*i+j]=c[i]+d[j];
sort(cd,cd+n*n);
long long res=;
for(i=;i
for(j=;j
{
int s=-a[i]-b[j];
res+=upper_bound(cd,cd+n*n,s)-lower_bound(cd,cd+n*n,s);
}
cout<
return ;
}
对着库函数的二分实现一下,库函数的二分实现
#include
using namespace std;
const int m=;
int n,a[m],b[m],c[m],d[m],cd[m*m];
int low(int key)
{
int step,mid,L=,R=n*n;
while(R>)
{
step=R>>,mid=L+step;
key>cd[mid]?(L=mid+,R=R-step-):(R=step);
}
return L;
}
int up(int key)
{
int step,mid,L=,R=n*n;
while(R>)
{
step=R>>,mid=L+step;
key>=cd[mid]?(L=mid+,R=R-step-):(R=step);
}
return L;
}
int main()
{
int i,j;
long long sum=;
scanf("%d",&n);
for(i=; i
scanf("%d",&a[i]);
for(i=; i
scanf("%d",&b[i]);
for(i=; i
scanf("%d",&c[i]);
for(i=; i
scanf("%d",&d[i]);
for(i=; i
for(j=; j
cd[i*n+j]=c[i]+d[j];
sort(cd,cd+n*n);
for(i=; i
for(j=; j
{
int s=-a[i]-b[j];
sum+=up(s)-low(s);
}
cout<
return ;
}
没学会二分的这里看
#include
#include
#define m 4005
int n,a[m],b[m],c[m],d[m],cd[m*m];
int low(int t)
{
int l=,r=n*n;
while(l
{
int mi=l+(r-l)/;
if(cd[mi]
else r=mi;
}
return l;
}
int up(int t)
{
int l=,r=n*n;
while(l
{
int mi=l+(r-l)/;
if(cd[mi]<=t)l=mi+;
else r=mi;
}
return l;
}
int main()
{
int i,j;
long long sum=;
scanf("%d",&n);
for(i=; i
scanf("%d",&a[i]);
for(i=; i
scanf("%d",&b[i]);
for(i=; i
scanf("%d",&c[i]);
for(i=; i
scanf("%d",&d[i]);
for(i=; i
for(j=; j
cd[i*n+j]=c[i]+d[j];
std::sort(cd,cd+n*n);
for(i=; i
for(j=; j
{
int s=-a[i]-b[j];
sum+=up(s)-low(s);
}
printf("%I64d",sum);
return ;
}
简单的实现,有点慢
利用绝对值很小去hash,solution from zhouzexi
#include
using namespace std;
unordered_mapmp[],mo;
int main(){
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
int n,x;
int T=;
cin>>n;
while(T--)
for(int i=;i
cin>>x;
mp[T][x]++;
}
unordered_map::iterator it,it2;
for(it=mp[].begin();it!=mp[].end();it++)
for(it2=mp[].begin();it2!=mp[].end();it2++)
mo[it->first+it2->first]+=it->second*it2->second;
__int64 s=;
for(it=mp[].begin();it!=mp[].end();it++)
for(it2=mp[].begin();it2!=mp[].end();it2++)
s+=1LL*mo[-(it->first+it2->first)]*it->second*it2->second;
cout<
}
数组的hash,可以0ms
#include
using namespace std;
int ans[], M[][];
int main()
{
//freopen("test.in","r",stdin);
ios::sync_with_stdio(false), cin.tie(), cout.tie();
int n;
cin >> n;
int ma = , mi = ;
for (int j = ; j < ; j++)
for (int i = , x; i < n; i++)
{
cin >> x;
x = x + ;
ma = max(ma, x);
mi = min(mi, x);
M[j][x]++;
}
for (int i = mi; i <= ma; i++)
for (int j = mi; j <= ma; j++)
ans[i + j] += M[][i] * M[][j];
long long s = ;
for (int i = mi; i <= ma; i++)
for (int j = mi; j <= ma; j++)
s += 1LL * ans[ - (i + j)] * (M[][i] * M[][j]);
cout << s << endl;
}