BZOJ2326: [HNOI2011]数学作业

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 955  Solved: 535
[Submit][Status]

Description

题解:

第一次知道矩阵乘法还能这样用,真是太神了!

我想到了递推式:

f[i]=(f[i-1]*10^len[i]+i) mod p

但是我没有办法用矩阵乘法来解决这样 f[i]=a*f[i-1]+b 但a和b都随着 i 的变化而变化

可以分位数来消掉a的变化,但是b我无法解决。

看了题解之后发现居然还可以这样!

把矩阵增一维

(f[i-1],i-1,1)*(10^len(i),0 0  =(f[i],i,1)

                         1,1,0

                         1,1,1)

简直太神了!原来矩阵不仅可以快速求解 线性递推式,还可以求解这样的,只要把变化的量一同加入矩阵的表示中即可。

题外话:
不会写 c++ 的矩阵快速幂,只好上pascal了。。。

边界要注意,想清楚了再写。

矩阵满足结合律,不满足交换律。

代码:

 1 type matrix=array[1..3,1..3] of int64;
 2 var a,b,c:matrix;
 3     m:array[0..18] of int64;
 4     i,j:longint;
 5     cs,n,p:int64;
 6     s:string;
 7 operator *(a,b:matrix)c:matrix;
 8  var i,j,k:longint;
 9  begin
10    fillchar(c,sizeof(c),0);
11    for i:=1 to 3 do
12     for j:=1 to 3 do
13      for k:=1 to 3 do
14       c[i,j]:=(c[i,j]+(a[i,k]*b[k,j] mod p)) mod p;
15  end;
16 procedure main;
17  begin
18    m[0]:=1;
19    for i:=1 to 18 do m[i]:=m[i-1]*10;
20    readln(n,p);str(n,s);
21    fillchar(b,sizeof(b),0);
22    for i:=1 to 3 do b[i,i]:=1;
23    for i:=1 to length(s) do
24     begin
25      if i<>length(s) then cs:=m[i]-m[i-1] else cs:=n-m[length(s)-1]+1;
26      a[1,1]:=m[i] mod p;a[1,2]:=0;a[1,3]:=0;
27      a[2,1]:=1;a[2,2]:=1;a[2,3]:=0;
28      a[3,1]:=1;a[3,2]:=1;a[3,3]:=1;
29      while cs>0 do
30       begin
31        if cs and 1=1 then b:=b*a;
32        cs:=cs>>1;
33        a:=a*a;
34       end;
35     end;
36    writeln(b[3,1]);
37  end;
38 
39 begin
40   assign(input,'input.txt');assign(output,'output.txt');
41   reset(input);rewrite(output);
42   main;
43   close(input);close(output);
44 end.   
View Code

 

 
posted @ 2014-08-22 22:51  ZYF-ZYF  Views(201)  Comments(4Edit  收藏  举报