题目大意: 给定 4 个 n(1 <= n <= 4000) 元素集合 A, B, C, D, 要求分别从中选取一个元素 a, b, c, d, 使得 a+b+c+d = 0, 问有多少种选法.
method 1:
这里用到一个很实用的技巧:
求长度为 n 的有序数组 a 中的数 k 的个数 num?
- num=upper_bound(a,a+n,k)-lower_bound(a,a+n,k);
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- #include <map>
- using namespace std;
- const int maxn=4000+10;
- int T,n,A[maxn],B[maxn],C[maxn],D[maxn],sum[maxn*maxn];long long ans=0;
- int main()
- {
- ios::sync_with_stdio(false);cin.tie(0);
- cin>>T;
- while(T--){
- ans=0;
- cin>>n;
- memset(sum,0,sizeof(sum));
- for(int i=0;i<n;i++){
- cin>>A[i]>>B[i]>>C[i]>>D[i];
- }
- int cnt=0;
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++){
- sum[cnt++]=A[i]+B[j];
- }
- }
- sort(sum,sum+cnt);
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++){
- ans+=upper_bound(sum,sum+cnt,-C[i]-D[j])-lower_bound(sum,sum+cnt,-C[i]-D[j]);
- }
- }
- cout<<ans<<endl;
- if(T) cout<<endl;
- }
- return 0;
- }
method 2: 运用 hash 的思想来做, 类似于 hdu1496 http://www.cnblogs.com/Fy1999/p/9355319.html
但需要加一个 hash 的结构体, 否则会导致超时
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- #include <map>
- using namespace std;
- const int maxn=4000+10;
- int T,n,A[maxn],B[maxn],C[maxn],D[maxn];
- long long ans=0;
- struct HashMAP{
- static const int mask = 0x7fffff;
- int p[8388608],q[8388608];
- void Clear()
- {
- for(int i=0;i<=mask; ++ i) q[i]=0;
- }
- int& operator [] (int k){
- int i;
- for(i=k&mask; q[i]&&p[i]!=k;i=(i+1)&mask) ;
- p[i]=k;
- return q[i];
- }
- }Hash;
- int main()
- {
- ios::sync_with_stdio(false);cin.tie(0);
- cin>>T;
- while(T--){
- Hash.Clear();// 忘记清零导致 TLE 了...TLE 不是 WA 有点坑啊......
- ans=0;
- 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 j=0;j<n;j++){
- Hash[A[i]+B[j]]++;
- }
- }
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++){
- ans+=Hash[-(C[i]+D[j])];
- }
- }
- cout<<ans<<endl;
- if(T) cout<<endl;
- }
- return 0;
- }
来源: http://www.bubuko.com/infodetail-2705344.html