标签:nod write close int gif opened ram closed ogr
首先我们需要排个序,如果排序之后相邻两项差超过1就是无解。统计一下每个数出现的次数num[i]。
然后我们很容易发现,一个完美序列,去掉所有权值大于某个值的数之后,还是完美的。
这样我们就考虑一路dp过去,将每一种数插进去。然后发现,当前数的决策之和上一个数有关。我们插的位置实际上只有两种可能:两边都是上一种数,一边是上一种数而且另一边没有数。这样状态比较好记录,只要记录上一种数有多少个连续的段和有有没有放在左右两边就好了。假如第i种数被分成了x段,考虑第一种情况,那就可以转移到第i+1种数被分成1..x-num[i]段,组合数算一下,应该比较好搞。有没有放在左右两边也可以讨论,非常简单。可以参考代码。
1 program j01; 2 const maxn=30086;mo=1000000007; 3 var a:array[0..maxn]of longint; 4 c:array[0..200,0..200]of int64; 5 num:array[0..maxn]of longint; 6 cnt,i,j,k,n,sp:longint; 7 ans:int64; 8 f:array[0..maxn,0..100,0..3]of int64; 9 10 procedure sort(l,r:longint); 11 var i,j,x,y:longint; 12 begin 13 i:=l;j:=r;x:=a[(i+j)div 2]; 14 repeat 15 while a[i]<x do inc(i); 16 while x<a[j] do dec(j); 17 if i<=j then 18 begin 19 y:=a[i];a[i]:=a[j];a[j]:=y; 20 inc(i);dec(j); 21 end; 22 until i>j; 23 if i<r then sort(i,r); 24 if l<j then sort(l,j); 25 end; 26 27 procedure pre; 28 var i:longint; 29 begin 30 sort(1,n); 31 cnt:=1;num[1]:=1; 32 for i:=2 to n do 33 begin 34 if a[i]-a[i-1]>1 then 35 begin 36 writeln(0);halt; 37 end; 38 if a[i]<>a[i-1] then inc(cnt); 39 inc(num[cnt]); 40 end; 41 c[0,0]:=1; 42 for i:=1 to 200 do 43 begin 44 c[i,0]:=1; 45 for j:=1 to i do c[i,j]:=(c[i-1,j]+c[i-1,j-1])mod mo; 46 end; 47 end; 48 49 begin 50 readln(n); 51 for i:=1 to n do read(a[i]); 52 pre; 53 f[1,1,3]:=1; 54 for i:=1 to cnt-1 do 55 begin 56 for j:=1 to num[i] do 57 begin 58 sp:=num[i]-j; 59 if f[i,j,0]>0 then 60 for k:=1 to sp do 61 f[i+1,k,0]:=(f[i+1,k,0]+f[i,j,0]*c[sp,k]mod mo*c[num[i+1]-1,k-1]mod mo)mod mo; 62 if f[i,j,1]>0 then 63 begin 64 for k:=1 to sp do 65 f[i+1,k,0]:=(f[i+1,k,0]+f[i,j,1]*c[sp,k]mod mo*c[num[i+1]-1,k-1]mod mo)mod mo; 66 for k:=0 to sp do 67 f[i+1,k+1,1]:=(f[i+1,k+1,1]+f[i,j,1]*c[sp,k]mod mo*c[num[i+1]-1,k]mod mo)mod mo; 68 end; 69 if f[i,j,2]>0 then 70 begin 71 for k:=1 to sp do 72 f[i+1,k,0]:=(f[i+1,k,0]+f[i,j,2]*c[sp,k]mod mo*c[num[i+1]-1,k-1]mod mo)mod mo; 73 for k:=0 to sp do 74 f[i+1,k+1,2]:=(f[i+1,k+1,2]+f[i,j,2]*c[sp,k]mod mo*c[num[i+1]-1,k]mod mo)mod mo; 75 end; 76 if f[i,j,3]>0 then 77 begin 78 for k:=1 to sp do 79 f[i+1,k,0]:=(f[i+1,k,0]+f[i,j,3]*c[sp,k]mod mo*c[num[i+1]-1,k-1]mod mo)mod mo; 80 for k:=0 to sp do 81 f[i+1,k+1,1]:=(f[i+1,k+1,1]+f[i,j,3]*c[sp,k]mod mo*c[num[i+1]-1,k]mod mo)mod mo; 82 for k:=0 to sp do 83 f[i+1,k+1,2]:=(f[i+1,k+1,2]+f[i,j,3]*c[sp,k]mod mo*c[num[i+1]-1,k]mod mo)mod mo; 84 for k:=2 to sp+2 do 85 f[i+1,k,3]:=(f[i+1,k,3]+f[i,j,3]*c[sp,k-2]mod mo*c[num[i+1]-1,k-1]mod mo)mod mo; 86 end; 87 end; 88 end; 89 ans:=0; 90 for i:=1 to num[cnt] do 91 ans:=(ans+f[cnt,i,0]+f[cnt,i,1]+f[cnt,i,2]+f[cnt,i,3])mod mo; 92 writeln(ans); 93 end.
标签:nod write close int gif opened ram closed ogr
原文地址:http://www.cnblogs.com/oldjang/p/6918958.html