bzoj3139: [Hnoi2013]比赛

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≤440%的数据满足N≤660%的数据满足N≤8100%的数据满足3≤N≤10且至少存在一组解。

Output

仅包含一个整数,表示答案对10^9+7取模的结果

Sample Input

4
4 3 6 4

Sample Output

3
 
 
题解:http://blog.csdn.net/thy_asdf/article/details/50418791
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 12
 7 #define mod 1000000007
 8 #define base1 31
 9 #define mod1 99997
10 #define base2 97
11 #define mod2 480881
12 #define maxnode 1000000
13 using namespace std;
14 char ch;
15 bool ok;
16 void read(int &x){
17     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
18     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
19     if (ok) x=-x;
20 }
21 int n,list[maxn];
22 struct state{
23     int tot,hash[mod1],pre[maxnode],key[maxnode],ans[maxnode];
24     int find(int st,int n){
25         int u=st,v=st;
26         for (int i=1;i<=n;i++) u=(u*base1+list[i]+1)%mod1;
27         for (int i=1;i<=n;i++) v=(v*base2+list[i]+1)%mod2;
28         for (int p=hash[u];p;p=pre[p]) if (key[p]==v) return ans[p];
29         return -1;
30     }
31     void add(int st,int n,int tmp){
32         int u=st,v=st;
33         for (int i=1;i<=n;i++) u=(u*base1+list[i]+1)%mod1;
34         for (int i=1;i<=n;i++) v=(v*base2+list[i]+1)%mod2;
35         pre[++tot]=hash[u],hash[u]=tot,key[tot]=v,ans[tot]=tmp;
36     }
37 }S;
38 int dfs(int st,int n){
39     if (n==1&&!list[n]) return 1;
40     if (n==1&&list[n]) return 0;
41     if (st==n&&list[n]) return 0;
42     if (st==n&&!list[n]) return dfs(1,n-1);
43     if (st==1){
44         int sum=0;
45         for (int i=1;i<=n;i++) sum+=list[i];
46         if (sum<n*(n-1)||sum>3*n*(n-1)/2) return 0;
47     }
48     if (st==1) sort(list+1,list+n+1);
49     int ans;
50     if (st==1){
51         ans=S.find(st,n);
52         if (ans!=-1) return ans;
53     }
54     int res[maxn];
55     if (!list[n]){
56         for (int i=st;i<n;i++) if (list[i]<3) return 0;
57         for (int i=1;i<=n;i++) res[i]=list[i];
58         for (int i=st;i<n;i++) list[i]-=3;
59         ans=dfs(1,n-1);
60         for (int i=1;i<=n;i++) list[i]=res[i];
61         if (st==1) S.add(st,n,ans);
62         return ans;
63     }
64     for (int i=1;i<=n;i++) res[i]=list[i];
65     ans=0;
66     if (list[n]-1<=(n-st-1)*3&&list[st]>=1&&list[n]>=1) list[n]--,list[st]--,ans+=dfs(st+1,n),ans%=mod;
67     for (int i=1;i<=n;i++) list[i]=res[i];
68     if (list[n]>=3) list[n]-=3,ans+=dfs(st+1,n),ans%=mod;
69     for (int i=1;i<=n;i++) list[i]=res[i];
70     if (list[n]<=(n-st-1)*3&&list[st]>=3) list[st]-=3,ans+=dfs(st+1,n),ans%=mod;
71     for (int i=1;i<=n;i++) list[i]=res[i];
72     if (st==1) S.add(st,n,ans);
73     return ans;
74 }
75 int main(){
76     read(n);
77     for (int i=1;i<=n;i++) read(list[i]);
78     printf("%d\n",dfs(1,n));
79     return 0;
80 }

 

posted @ 2015-12-28 17:29  chenyushuo  阅读(255)  评论(0编辑  收藏  举报