题目描述 Description
沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联赛共N只队伍参加,比赛规则如下:
(1) 每两支球队之间踢一场比赛。
(2) 若平局,两支球队各得1分。
(3) 否则胜利的球队得3分,败者不得分。
尽管非常遗憾没有观赏到精彩的比赛,但沫沫通过新闻知道了每支球队的最后总得分,然后聪明的她想计算出中多少种可能的比赛情况。
但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对109+7取模的结果。
输入描述 Input Description
第一行是一个正整数N。
接下来一行N个非负整数,依次表示各队的最后得分。
输入保证20%的数据满足N≤4,40%的数据满足N≤6,60%的数据满足N≤8,100%的数据满足3≤N≤10.
输出描述 Output Description
输入答案mod 10^9+7
样例输入 Sample Input
4
4 3 6 4
样例输出 Sample Output
3
其实想一想,还真是那个道理,不是你不懂,是你不敢去做,不敢去想
每一个对于一个得分序列,不管怎么交换,都不会影响答案,所以我们可以用记忆化搜索,hash一下当前的状态
但是这个状态必须是i个人,两两之间都没比赛的情况
我们爆搜每一个人的比赛情况,然后记忆化一下,如果以前已经搜过了,就直接返回答案
看了题解说状态只有40000左右,我就只开了80000的hash
1 const 2 h=30077; 3 mo=1000000007; 4 var 5 a,s:array[0..10]of longint; 6 nsum,num:array[0..80000]of int64; 7 next:array[0..80000]of longint; 8 n,ans,sum,yes,no,tot:longint; 9 c:array[0..27]of longint; 10 11 procedure init; 12 var 13 i,j,t:longint; 14 begin 15 read(n); 16 for i:=1 to n do 17 begin 18 read(a[i]); 19 inc(sum,a[i]); 20 end; 21 yes:=sum-n*(n-1); 22 no:=n*(n-1)>>1-yes; 23 for i:=n downto 2 do 24 for j:=1 to i-1 do 25 if a[j]>a[j+1] then 26 begin 27 t:=a[j]; 28 a[j]:=a[j+1]; 29 a[j+1]:=t; 30 end; 31 end; 32 33 function hash(x:int64):longint; 34 begin 35 exit(trunc(x*10007 mod h)); 36 end; 37 38 function find(x:int64):boolean; 39 var 40 i:longint; 41 begin 42 i:=hash(x); 43 while i<>0 do 44 begin 45 if num[i]=x then exit(true); 46 i:=next[i]; 47 end; 48 exit(false); 49 end; 50 51 procedure insert(s,x:int64); 52 var 53 i:longint; 54 begin 55 i:=hash(s); 56 while (num[i]<>s)and(next[i]<>0) do 57 i:=next[i]; 58 if num[i]=s then nsum[i]:=(nsum[i]+x)mod mo 59 else 60 begin 61 inc(tot); 62 next[i]:=tot; 63 num[tot]:=s; 64 nsum[tot]:=x; 65 end; 66 end; 67 68 function get(x:int64):int64; 69 var 70 i:longint; 71 begin 72 i:=hash(x); 73 while (num[i]<>x)and(next[i]<>0) do 74 i:=next[i]; 75 if num[i]=x then exit(nsum[i]) 76 else exit(0); 77 end; 78 79 function dfs(x,y:longint):int64; 80 var 81 i,j,xi,yi:longint; 82 ss:int64; 83 begin 84 if x=n then exit(1); 85 if y=x+1 then 86 begin 87 ss:=0; 88 fillchar(c,sizeof(c),0); 89 for i:=x to n do 90 inc(c[a[i]-s[i]]); 91 for i:=27 downto 0 do 92 for j:=1 to c[i] do 93 ss:=ss*28+i; 94 if find(ss) then exit(get(ss)); 95 end; 96 dfs:=0; 97 if (s[x]+(n-y+1)*3<a[x])or(s[x]+yes*3+(n-y+1-yes)<a[x]) then exit(dfs); 98 if y=n then 99 begin 100 xi:=x+1; 101 yi:=xi+1; 102 end 103 else 104 begin 105 xi:=x; 106 yi:=y+1; 107 end; 108 if yes>0 then 109 begin 110 if s[x]+3<=a[x] then 111 if (y<n)or((y=n)and(s[x]+3=a[x])) then 112 begin 113 dec(yes); 114 inc(s[x],3); 115 dfs:=(dfs+dfs(xi,yi))mod mo; 116 inc(yes); 117 dec(s[x],3); 118 end; 119 if s[y]+3<=a[y] then 120 if (y<n)or((y=n)and(s[x]=a[x])) then 121 begin 122 dec(yes); 123 inc(s[y],3); 124 dfs:=(dfs+dfs(xi,yi))mod mo; 125 inc(yes); 126 dec(s[y],3); 127 end; 128 end; 129 if no>0 then 130 if (s[x]+1<=a[x])and(s[y]+1<=a[y]) then 131 if (y<n)or((y=n)and(s[x]+1=a[x])) then 132 begin 133 dec(no); 134 inc(s[x]); 135 inc(s[y]); 136 dfs:=(dfs+dfs(xi,yi))mod mo; 137 inc(no); 138 dec(s[x]); 139 dec(s[y]); 140 end; 141 if y=x+1 then insert(ss,dfs); 142 end; 143 144 begin 145 init; 146 tot:=h; 147 write(dfs(1,2)); 148 end.