• 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
  • 相关阅读:
    (转)《深入理解java虚拟机》学习笔记9——并发编程(一)
    (转)《深入理解java虚拟机》学习笔记8——Tomcat类加载器体系结构
    (转)《深入理解java虚拟机》学习笔记7——Java虚拟机类生命周期
    (转)《深入理解java虚拟机》学习笔记6——类加载机制
    (转)《深入理解java虚拟机》学习笔记5——Java Class类文件结构
    (转)《深入理解java虚拟机》学习笔记4——Java虚拟机垃圾收集器
    (转)《深入理解java虚拟机》学习笔记3——垃圾回收算法
    (转)《深入理解java虚拟机》学习笔记2——Java内存溢出实例
    (转)《深入理解java虚拟机》学习笔记1——Java内存结构
    Zookeeper安装
  • 原文地址:https://www.cnblogs.com/oldjang/p/6918958.html
Copyright © 2020-2023  润新知