HDU 3306 - Another kind of Fibonacci
给你 A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2).
求 S(N) = A(0) 2 +A(1) 2+……+A(n) 2.
由于线性代数只能做线性变换,故要得出 A(n) 2 的递推式
A(n) 2 =X2A(N-1)2+Y2A(N-2)2+2XYA(N-1)A(N-2);
难点就在于 A(N-1)A(N-2) 这一项
故找到此项递推式
A(N-1)A(N-2) = (XA(N-2)+YA(N-3))*A(N-2) = XA(N-2)2+YA(N-2) A(N-3);
就可以写成矩阵
|1 X2 Y2 2XY| | S(n-1) | | S(n) |
|0 X2 Y2 2XY| * | A(n-1)2 | = | A(n)2 |
|0 0 1 0 | |A(n-2)2 | |A(n-1)2 |
|0 0 X Y | |A(n-2)A(n-3)| |A(n-1)A(n-2)|
剩下就是矩阵快速幂了
#include <iostream> #include <cstdio> #include <cstring> using namespace std; struct P{ int a[65][65]; }c,s,q; int n,k,mod; int a[35][35]; void ini() { memset(s.a,0,sizeof(s.a)); for(int i=1;i<=n;i++) s.a[i][i]=1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) s.a[i][j+n]=s.a[i+n][j+n]=a[i][j]; memset(q.a,0,sizeof(q.a)); for(int i=1;i<=n;i++) q.a[i+n][i]=1; } P mult(const P& a,const P& b) { P c; for(int i=1;i<=2*n;++i) { for(int j=1;j<=2*n;++j) { c.a[i][j]=0; for(int k=1;k<=2*n;k++) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j] )%mod; } } return c; } void fuc(int p) { memset(c.a,0,sizeof(c.a)); for(int i=1;i<=n*2;i++) c.a[i][i]=1; while(p) { if(p&1) c=mult(c,s); s=mult(s,s); p>>=1; } } int main() { while(~scanf("%d%d%d",&n,&k,&mod)) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); a[i][j]%mod; } } ini(); fuc(k); P ans; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { ans.a[i][j]=0; for(int k=i;k<=2*n;k++) ans.a[i][j]=(ans.a[i][j]+c.a[i][k]*q.a[k][j] )%mod; } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) printf("%d ",ans.a[i][j]); puts(""); } } }
我自倾杯,君且随意