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
原文地址:https://www.cnblogs.com/phile/p/4473009.html