1. 程式人生 > >HiHo1505:小Hi和小Ho的禮物(Meet-In-The-Middle + 組合數學)

HiHo1505:小Hi和小Ho的禮物(Meet-In-The-Middle + 組合數學)

整數 image namespace 多少 max using for 2種 100%

時間限制: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

技術分享

Code:

技術分享
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 static const int MAXN = 1e3 + 10;
 4 static const int HS = 2000000
+ 10; 5 typedef long long LL; 6 struct Node 7 { 8 int x , y , num; 9 Node() 10 { 11 num = 0; 12 } 13 }; 14 LL vis[HS]; 15 LL dvis[HS]; 16 LL data[MAXN]; 17 LL ans; 18 int n; 19 int main() 20 { 21 scanf("%d" , &n); 22 for(int i = 1 ; i <= n ; ++i)
23 scanf("%lld" , &data[i]) , ++dvis[data[i]]; 24 for(int i = 1 ; i <= n ; ++i) 25 { 26 for(int j = i + 1 ; j <= n ; ++j) 27 { 28 ++vis[data[i] + data[j]]; 29 } 30 } 31 32 for(int i = 1 ; i <= n ; ++i) 33 { 34 for(int j = i + 1 ; j <= n ; ++j) 35 { 36 if(data[i] != data[j]) 37 { 38 LL a = dvis[data[i]] , b = dvis[data[j]]; 39 LL sum = data[i] + data[j]; 40 ans += vis[sum] - (a * b - (a - 1) * (b - 1)); 41 } 42 else 43 { 44 LL sum = data[i] + data[j]; 45 LL pre = dvis[data[i]]; 46 LL last = pre - 2; 47 ans += vis[sum] - (pre * (pre - 1) - last * (last - 1)) / 2; 48 } 49 } 50 } 51 printf("%lld" , ans); 52 }
View Code

HiHo1505:小Hi和小Ho的禮物(Meet-In-The-Middle + 組合數學)