Description
沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联 赛共N支球队参加,比赛规则如下:
(1) 每两支球队之间踢一场比赛。 (2) 若平局,两支球队各得1分。
(3) 否则胜利的球队得3分,败者不得分。
尽管非常遗憾没有观赏到精彩的比赛,但沫沫通过新闻知道了每只球队的最后总得分, 然后聪明的她想计算出有多少种可能的比赛过程。
譬如有3支球队,每支球队最后均积3分,那么有两种可能的情况:
可能性1 可能性2
球队 A B C 得分 球队 A B C 得分
A - 3 0 3 A - 0 3 3
B 0 - 3 3 B 3 - 0 3
C 3 0 - 3 C 0 3 - 3
但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算 出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对109+7取模的结果
Input
第一行是一个正整数N,表示一共有N支球队。 接下来一行N个非负整数,依次表示各队的最后总得分。
输入保证20%的数据满足N≤4,40%的数据满足N≤6,60%的数据满足N≤8,100%的数据 满足3≤N≤10且至少存在一组解。
Output
仅包含一个整数,表示答案对10^9+7取模的结果
Sample Input
4 3 6 4
Sample Output
题解
我们令$f(l, r)$表示考虑$l$和$r$比赛,按$l$为主,若$l == r$,则$l++$。
考虑直接爆搜的话,就是枚举当前的与之后的每一个比赛的结果是什么,但是复杂度很高。
优化的话,考虑我枚举完一个的得分之后,剩下的状态打乱顺序不会影响最终结果,因为前面的贡献已经计算完毕了。
那么我每次从小到大排序,并且把状态压起来,记忆化一下,就可以通过官方数据了,还有诸如鸡兔同笼和得分上限的剪枝也可以加。
1 //It is made by Awson on 2017.10.11 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <cmath> 7 #include <stack> 8 #include <queue> 9 #include <vector> 10 #include <string> 11 #include <cstdio> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 #define LL long long 17 #define Min(a, b) ((a) < (b) ? (a) : (b)) 18 #define Max(a, b) ((a) > (b) ? (a) : (b)) 19 #define sqr(x) ((x)*(x)) 20 using namespace std; 21 const int MOD = 1000000007; 22 23 int n, a[15]; 24 map<LL, int>mp[15]; 25 26 LL get_hash(int *a) { 27 LL sum = 0; 28 for (int i = 1; i <= n; i++) 29 sum = sum*28+a[i]; 30 return sum; 31 } 32 int dfs(int *a, int l, int r) { 33 if (3*(r-l) < a[l]) return 0; 34 if (l == r) { 35 if (l == n) return 1; 36 int b[15]; for (int i = 1; i <= n; i++) b[i] = a[i]; 37 sort(b+1, b+n+1); 38 LL tmp = get_hash(b); 39 if (mp[l+1].count(tmp) == 1) return mp[l+1][tmp]; 40 return mp[l+1][tmp] = dfs(b, l+1, n); 41 } 42 int tol = 0; 43 if (a[l] >= 3) { 44 a[l] -= 3; 45 (tol += dfs(a, l, r-1)) %= MOD; 46 a[l] += 3; 47 } 48 if (a[l] >= 1 && a[r] >= 1) { 49 a[l] -= 1, a[r] -= 1; 50 (tol += dfs(a, l, r-1)) %= MOD; 51 a[l] += 1, a[r] += 1; 52 } 53 if (a[r] >= 3) { 54 a[r] -= 3; 55 (tol += dfs(a, l, r-1)) %= MOD; 56 a[r] += 3; 57 } 58 return tol; 59 } 60 void work() { 61 scanf("%d", &n); 62 for (int i = 1; i <= n; i++) 63 scanf("%d", &a[i]); 64 sort(a+1, a+n+1); 65 printf("%d ", dfs(a, 1, n)); 66 } 67 int main() { 68 work(); 69 return 0; 70 }