首页 > 代码库 > 矩阵十题【四】 HDU 3306 Another kind of Fibonacci
矩阵十题【四】 HDU 3306 Another kind of Fibonacci
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3306
题目大意:A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2);给定三个值N,X,Y求S(N):S(N) = A(0)^2 +A(1)^2+……+A(n)^2。
学了这几题,还是不太很懂,后来看题解,渐渐也是懂了一点。
题目的意思是求出A(0)^2 +A(1)^2+……+A(n)^2
考虑1*4 的矩阵【s[n-2],a[n-1]^2,a[n-2]^2,a[n-1]*a[n-2]】
我们需要找到一个4×4的矩阵A,使得它乘以A得到1×4的矩阵
【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】
即:【s[n-2],a[n-1]^2,a[n-2]^2,a[n-1]*a[n-2]】* A = 【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】
= 【s[n-2]+a[n-1]^2 , x^2 * a[n-1]^2 + y^2 * a[n-2]^2 + 2*x*y*a[n-1]*a[n-2] ,
a[n-1]^2 , x*a[n-1]^2 + y*a[n-2]a[n-1]】
可以构造矩阵A为:
1 0 0 0
1 x^2 1 x
0 y^2 0 0
0 2xy 0 y
故:【S[0],a[1]^2,a[0]^2,a[1]*a[0]】 * A^(n-1) = 【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】
所以:【S[0],a[1]^2,a[0]^2,a[1]*a[0]】 * A^(n) = 【s[n],a[n+1]^2,a[n]^2,a[n+1]*a[n]】
若A = (B * C ) 则AT = ( B * C )T = CT * BT
#include<stdio.h> #include<string.h> #define N 4 #define M 10007 struct Matrix { __int64 a[N][N]; }res,tmp,ans,origin; Matrix A={1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,0,0}; //相当于那个1*4的矩阵的转置,即[s0,a1^2,a0^2,a1*a0]T Matrix mul(Matrix x,Matrix y) { int i,j,k; memset(tmp.a,0,sizeof(tmp.a)); for(i=0;i<4;i++) for(j=0;j<4;j++) for(k=0;k<4;k++) { tmp.a[i][j]+=(x.a[i][k]*y.a[k][j])%M; tmp.a[i][j]%=M; } return tmp; } Matrix quickpow(int k) { int i; memset(res.a,0,sizeof(res.a)); for(i=0;i<4;i++) res.a[i][i]=1; while(k) { if(k&1) res=mul(res,origin); origin=mul(origin,origin); k>>=1; } return res; } int main() { int n,x,y; while(scanf("%d%d%d",&n,&x,&y)!=EOF) { x%=M; y%=M; memset(origin.a,0,sizeof(origin.a)); origin.a[0][0]=origin.a[0][1]=origin.a[2][1]=1; origin.a[1][1]=(x*x)%M; origin.a[1][2]=(y*y)%M; origin.a[1][3]=(2*x*y)%M; origin.a[3][1]=x; origin.a[3][3]=y; res=quickpow(n); //求构造出的矩阵A^n ans=mul(res,A); //A^n * [s0,a1^2,a0^2,a1*a0]T printf("%I64d\n",ans.a[0][0]%M); } return 0; }