• 51nod1780 完美序列


      首先我们需要排个序,如果排序之后相邻两项差超过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.
    View Code
  • 相关阅读:
    演讲的灵魂:主线
    四种演讲风格应该被摒弃
    思想是演讲的基础
    DML&DDL&DCL
    kafka在windows下安装单机版
    《可复制的领导力》-领导力技术
    《可复制的领导力》-管理者角色
    《可复制的领导力》-沟通视窗
    《可复制的领导力》-领导和管理的区别
    vs code设置终端主题颜色
  • 原文地址:https://www.cnblogs.com/oldjang/p/6918958.html
Copyright © 2020-2023  润新知