hdu 3306
http://acm.hdu.edu.cn/showproblem.php?pid=3306
矩阵连乘求解。
首先我们列一个式子 A(n)=x*A(n-1)+b*A(n-2);
则A(n)^2=x^2*A(n-1)^2+y^2*A(n-2)^2+2*x*y*A(n-1)*A(n-2);
也就是说S(n)=S(n-1)+A(n)^2=S(n-1)+x^2*A(n-1)^2+y^2*A(n-2)^2+2*x*y*A(n-1)*A(n-2);
我们从中取出不能直接求解的部分构成一个矩阵M={S(n-1),A(n-1)^2,A(n-2)^2,A(n-1)*A(n-2)}
然后由此可以看出有一个辅助矩阵D={1 0 0 0
x^2 x^2 1 x
y^2 y^2 0 0
2*x*y 2*x*y 0 y}
第一列是S(n)与S(n-1)的转化方程
第二列是A(n)^2与A(n-1)^2的转化方程
第三列是为了将A(n-2)变为A(n-1)
第四列:
x*A(n-1)^2+y*A(n-1)*A(n-2)=(x*A(n-1)+y*A(n-2))*A(n-1)=A(n)*A(n-1)
由此的我们可以很方便的从S(n-1)求解出S(n),只需要一个辅助矩阵
然后为了提高效率,可以采用二进制的思想(二进制思想具体参见北大程序设计引导及在线实践的P169)
本题要对最终结果模10007,所以为了防止溢出,我们可以在乘法后立即模10007,不会改变数值(模定理具体参见白书180)
1 #include <stdio.h>
2 #include <memory.h>
3 #define SIZE 4
4 #define modle 10007
5
6 void ini_2(int x,int y,int (*matrix)[SIZE]) //初始化辅助矩阵
7 {
8 matrix[0][0]=matrix[1][2]=1;
9 matrix[0][1]=matrix[0][2]=matrix[0][3]=0;
10 matrix[2][2]=matrix[3][2]=matrix[2][3]=0;
11 matrix[1][0]=matrix[1][1]=(x*x)%modle;
12 matrix[2][0]=matrix[2][1]=(y*y)%modle;
13 matrix[3][0]=matrix[3][1]=(((x*y)%modle)*2)%modle;
14 matrix[1][3]=x;
15 matrix[3][3]=y;
16 }
17
18 void ini_1(int x,int y,int (*matrix)[SIZE]) //初始化主矩阵
19 {
20 memset(matrix,0,sizeof(matrix));
21 matrix[0][0]=2;
22 matrix[0][1]=1;
23 matrix[0][2]=1;
24 matrix[0][3]=1;
25 }
26
27 void matrix_mutiply(int (*matrix_1)[SIZE],int (*matrix_2)[SIZE]) //矩阵乘法
28 {
29 int matrix_cpy_1[4][4],matrix_cpy_2[4][4];
30 for(int i=0;i<4;i++)
31 for(int j=0;j<4;j++)
32 {
33 matrix_cpy_1[i][j]=matrix_1[i][j];
34 matrix_cpy_2[i][j]=matrix_2[i][j];
35 matrix_1[i][j]=0;
36 }
37 for(int i=0;i<4;i++)
38 for(int j=0;j<4;j++)
39 for(int k=0;k<4;k++)
40 matrix_1[i][j]+=matrix_cpy_1[i][k]*matrix_cpy_2[k][j],matrix_1[i][j]%=modle;
41 }
42 int main()
43 {
44 int matrix_1[SIZE][SIZE],matrix_2[SIZE][SIZE];
45 int number,x,y;
46 while(scanf("%d %d %d",&number,&x,&y)==3)
47 {
48 x%=modle,y%=modle;
49 ini_1(x,y,matrix_1);
50 ini_2(x,y,matrix_2);
51 number-=1;
52 while(number) //运用二进制提高效率
53 {
54 if(number&1)
55 matrix_mutiply(matrix_1,matrix_2);
56 matrix_mutiply(matrix_2,matrix_2);
57 number>>=1;
58 }
59 printf("%d\n",matrix_1[0][0]);
60 }
61 return 0;
62 }