• bzoj2004


    反正N<=10^9肯定是矩阵乘法
    反正p<=10肯定是状压dp
    首先有一个非常重要的性质是任意连续P个站,必须保证K辆车必须停在其中的一个站
    我们设f[i,S]表示到第i个站搞定了后,这K辆公交车停靠的站的状态集合为S的方案数
    由于公交车之间是等价的,因此我们只要知道这K辆公交车离当前站的距离(∈[0,p-1])
    显然这有一辆肯定距离当前站距离为0,剩下的k-1辆的距离显然在[1,p-1]中组合
    可知状态数为C(k-1,p-1),不难发现状态数最多是C(5,9)=126
    由此可以得到f[i,s]=∑f[i-1,s']
    显然我们可以弄出转移矩阵然后矩乘加速

     1 const mo=30031;
     2 
     3 var w:array[0..130,0..11] of boolean;
     4     v:array[0..11] of boolean;
     5     a,b,c,d:array[0..130,0..130] of longint;
     6     ch,m,n,k,p,i,j,h,ans:longint;
     7 
     8 procedure mul;
     9   var i,j,k:longint;
    10   begin
    11     for i:=1 to m do
    12       for j:=1 to m do
    13       begin
    14         c[i,j]:=0;
    15         for k:=1 to m do
    16           c[i,j]:=(c[i,j]+a[i,k]*b[k,j]) mod mo;
    17       end;
    18   end;
    19 
    20 procedure dfs(x,t:longint);
    21   var i:longint;
    22   begin
    23     if (p-x<k-t) then exit;
    24     if t=k+1 then
    25     begin
    26       inc(m);
    27       w[m]:=v;
    28     end;
    29     for i:=x to p do
    30     begin
    31       v[i]:=true;
    32       dfs(i+1,t+1);
    33       v[i]:=false;
    34     end;
    35   end;
    36 
    37 procedure quick(n:longint);
    38   var t,i,x:longint;
    39   begin
    40     x:=n;
    41     t:=0;
    42     while x<>0 do
    43     begin
    44       inc(t);
    45       x:=x shr 1;
    46     end;
    47     for i:=t-1 downto 0 do
    48     begin
    49       a:=c;
    50       b:=c;
    51       mul;
    52       if (1 shl i) and n<>0 then
    53       begin
    54         a:=c;
    55         b:=d;
    56         mul;
    57       end;
    58     end;
    59   end;
    60 
    61 begin
    62   readln(n,k,p);
    63   v[1]:=true;
    64   dfs(2,2);  //搜出所有状态
    65   for i:=1 to m do
    66     for j:=1 to m do
    67     begin
    68       ch:=1;
    69       for h:=1 to p do
    70         if w[i,h] and not w[j,h+1] then  //有一辆有停靠在当前站
    71         begin
    72           dec(ch);
    73           if ch<0 then break;
    74         end;
    75       if ch=0 then d[j,i]:=1;
    76     end;
    77 
    78   n:=n-k;
    79   for i:=1 to m do
    80     c[i,i]:=1;
    81   quick(n);
    82   writeln(c[1,1] mod mo);
    83 end.
    View Code
  • 相关阅读:
    Hibernate官方文档翻译-(第二章,入门)
    关于我的Blog
    退役记
    考场上要写的emacs
    关于在linux下将caps lock键改成ctrl的方法
    SXOI2020退役记
    min_25筛学习笔记
    带花树学习笔记
    [CF438E] 小朋友和二叉树
    多项式中步
  • 原文地址:https://www.cnblogs.com/phile/p/4473009.html
Copyright © 2020-2023  润新知