反正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.