#1505 : 小Hi和小Ho的礼物

#1505 : 小Hi和小Ho的礼物

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

某人有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


#include<bits/stdc++.h>
#define pb push_back
typedef long long ll;
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e3 + 10;
int a[maxn];
map<int, int> ma;
int cnt;
int n;
map<int, int> mc;
void solve() {
    cin >> n;

if(n < 4) {
    cout << 0 << endl;
        return;
}
for (int i = 0; i < n; i++) {
    cin >> a[i];
    //统计每个数出现的次数
    mc[a[i] ]++;
}
//map<int, int> ma;
for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
        //统计可能的和的个数
        ma[a[i] + a[j] ]++;
    }
}
    ll res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            // 枚举小hi可以拿的情况    
            if(a[i] != a[j])
                //计算小ho可以的情况
               //就像楼上说的
                res += ma[a[i] + a[j] ] - mc[a[i] ] * mc[a[j]] + (mc[a[i] ] -1) *( mc[a[j]] - 1);
            else {
                //相等的时候需要特别考虑
                int t = mc[a[i] ];
                int td = t;
                t -= 2;
                res += ma[a[i] + a[j] ] - td * (td - 1) / 2 + t * (t - 1) / 2;
            }

            //cout << ma[a[i] + a[j] ] << " " << mc[a[i] ] * mc[a[j]] << " " << (mc[a[i] ] -1) *( mc[a[j]] - 1) << endl;
            //cout << i << " " << j << " " << res << endl;

        }
    }
    cout << res << endl;
}

int main() {
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    solve();
    return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值