hihocode 1505 : 小Hi和小Ho的礼物

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ACM__dongsheng/article/details/70305850

描述

某人有N袋金币,其中第i袋内金币的数量是Ai。现在他决定选出2袋金币送给小Hi,再选2袋金币送给小Ho,同时使得小Hi和小Ho得到的金币总数相等。他想知道一共有多少种不同的选择方法。

具体来说,有多少种下标四元组(i, j, p, q)满足i, j, p, q两两不同,并且i < j, p < q, Ai + Aj = Ap + Aq。

例如对于数组A=[1, 1, 2, 2, 2],一共有12种选法:

i j p q
1 3 2 4
1 3 2 5
1 4 2 3
1 4 2 5
1 5 2 3
1 5 2 4
2 3 1 4
2 3 1 5
2 4 1 3
2 4 1 5
2 5 1 3
2 5 1 4

输入

第一行包含一个整数N。

第二行包含N个整数,A1, A2, A3 … AN。

对于70%的数据,1 <= N <= 100

对于100%的数据,1 <= N <= 1000, 1 <= Ai <= 1000000
输出

不同选择的数目。
样例输入

5  
1 1 2 2 2

样例输出

12

如果不考虑非法组合的话, 辣么 对于 a[i] + a[j] = a[q] + a[p] = M。 假如 有x 对 a[i] + a[j] = M 的话,答案就是 C(m,2).
考虑重复。 举个栗子, 对于序列, 1 1 2 2 2。 当你M = 3,选择(1,3)(下标)时,你再选择其他(a[q],a[p])的情况,你要去掉 下标(1,4,)(1,5)(3,2)。 也就是 包含(1,3)中某一个的情况。可以发现有 (n+m-2)n为1个数,m为3个数。

#include <iostream>
#include <cstring>
#include <map>
using namespace std;

const int maxn = 1e5+50;
#define FCIN  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
const int MAXINT = 0x7fffffff;
const int MININT = 0x80000000;
typedef long long LL;

int a[maxn]; 
int cou[10*maxn];
map<int,int> M;

int main(int argc, char* argv[] ){
   FCIN;
   int n; cin>>n;
   M.clear();
   memset(cou,0,sizeof(cou));

   for(int i=1;i<=n;i++) cin>>a[i],cou[a[i]]++;
   for(int i=1;i<=n;i++){
    for(int j=i+1;j<=n;j++){
        M[ a[i]+ a[j] ]++;
    }
   }
   LL ans = 0;
   for(int i=1;i<=n;i++){
    for(int j=i+1;j<=n;j++){
        if(a[i] != a[j]){
            ans += M[ a[i] + a[j] ] - (cou[a[i]] + cou[a[j]] -2) -1 ;
        }
        else{
            ans += M[ a[i] + a[j] ] - (cou[a[i]] + cou[a[j]] -4) - 1;
        }
    }
   } 
   cout<<ans<<endl;
   return 0;
}

猜你喜欢

转载自blog.csdn.net/ACM__dongsheng/article/details/70305850
今日推荐