题意
一年一度的高考结束了,我校要拍集体照。本届毕业生共分n个班,每个班的人数为Ai。这次拍集体照的要求非常奇怪:所有学生站一排,且相邻两个学生不能同班。现在,安排这次集体照的老师找到了你,想问问你一共有多少种方案。方案数可能很大,最终结果对1,000,000,007取模。
数据范围
对于30%,Sigma(Ai) <=10
对于另外10%,n=2
对于另外20%,n=3
对于100%,1<=n<=50,1<=Ai<=50, Sigma(Ai)<=1500
解决
30%——60%暴力。
100%:
动态规划
我们可以设
f[i,j]
为第i个班前面有j个是有问题的(即相邻的)。
那么答案便是
f[n,0]
。
那么我们如何去推
f[i,j]
呢?
我们可以从第i个入手,若是确定了j,那么第i+1的j是多少呢?
我们先考虑a[i+1]的情况,我们设p,q分别表示第i+1个班放入p个合法的空中,放在q个不合法的空里。那么明显的,放入q个不合法空便会使得那q个不合法的变成合法的(即11中间放一个2),而放在p个合法的是不会影响j的值。
那么我们再枚举b个为放在p个空中,那么便有a[i+1]-b个放在q个空中。
这时我们再考虑会影响多少j的值。
首先我们放b个在合法的,那么若我们每个空都放一个,那么便会多出b-p个数,这些数挤在一起,那么就会加上b-p个不合法。
然后放在q个空也类似,也要加去a[i+1]-b-q。
还要减去q个不合法的变成合法的,
所以最终的j为j+(a[i+1]-b-q)+(b-p)-q整理变成j+a[i+1]-2*q-p,b抵消了。
那么转移的答案便很简单了:
f[i+1,j-2*q-p+a[i+1]]+=f[i,j]*c(sum[i+1]+1-j,p)*c(j,q)*c(a[i+1]-1,p+q-1)
也就是在合法和不合法空中选q和p个空,还有a[i+1]分成p+q份的分法(每份必须有一个,且注意这个不是在算a[i+1]的排列)
这样便很好解决了问题了。
for i:=1 to n do
for j:=0 to sum[i-1] do
for p:=0 to a[i] do
for q:=0 to min(j,a[i]-p) do
f[i,j-2*q-p+a[i]]:=(f[i,j-2*q-p+a[i]]+
((((f[i-1,j]*c(sum[i-1]+1-j,p))mod mo)*c(j,q))mod mo)*c(a[i]-1,p+q-1))mod mo;
注意要排序a