HDU 3306 矩阵快速幂,构造矩阵方法详解

 

HDU  3306:传送门

Another kind of Fibonacci

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2636    Accepted Submission(s): 1052

 

 

Problem Description

 

 

As we all known , the Fibonacci series : F(0) = 1, F(1) = 1, F(N) = F(N - 1) + F(N - 2) (N >= 2).Now we define another kind of Fibonacci : A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2).And we want to Calculate S(N) , S(N) = A(0)2 +A(1)2+……+A(n)2.
 
 

 

Input

 

There are several test cases.
Each test case will contain three integers , N, X , Y .
N : 2<= N <= 231 – 1
X : 2<= X <= 231– 1
Y : 2<= Y <= 231 – 1
 

 

Output

 

For each test case , output the answer of S(n).If the answer is too big , divide it by 10007 and give me the reminder.
 

 

Sample Input

 

 
2 1 1 3 2 3
 

 

Sample Output

 

 
6 196

题意很简单:An=x*A(n-1)+y*A(n-2);A0=1,A1=1;S(n)=A0^2+A1^2+A2^2+…………+An^2;求Sn;  已知n,x,y;

 

思路:先找上一项和下一项的关系。(需要什么类型,求什么类型)

An=x*A(n-1) +y*A(n-2); A(n-1)  类型(一次方型)已知 )

求Sn: Sn 类型(总和型)未知 )

Sn = Sn-1 + An^2 ;   An^2 类型(平方型)未知 )

An^2=(x*A(n-1) +y*A(n-2))*(x*A(n-1) +y*A(n-2))=  x^2*A(n-1)^2  +  2*x*y*A(n-1)*A(n-2)  +  y^2*A(n-2)^2  ;

 A(n-1)*A(n-2) 类型(乘积型)未知 )

An*A(n-1) =(  x*A(n-1) +y*A(n-2)  )*A(n-1)  =   * A(n-1)^2  +  y * A(n-1)*A(n-2) ; (这个式子 开始的那个A(n-1) 不敢拆)

 所有类型都已知 )

所有的关系都有了就可以写矩阵了

初始矩阵 :

S(n-2),  A(n-1)^2 , A(n-2)^2 , A(n-1)*A(n-2) ;  

 

系数矩阵:

1       0       0         0      

1     x^2      1         x      

0     y^2      0         0           

0    2*x*y    0         y     

下一项矩阵:

S(n-1),  An^2 , A(n-1)^2 ,An*A(n-1) ;  

 

第0项矩阵为    S0 ,  A1^2  ,  A0^2  ,,  A1*A0

及1    1    1    1 

AC代码:

 

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#define LL long long
#include<iostream>
#define mod 10007
using namespace std;
struct node
{
    int a[10][10];
};
node operator * (node a,node b)
{
    node c;
    memset(c.a,0,sizeof(c.a));
    for(int i=0; i<4; i++)
        for(int j=0; j<4; j++)
        {
            for(int k=0; k<4; k++)
                c.a[i][j]+=a.a[i][k]*b.a[k][j];
            c.a[i][j]%=mod;
        }
return c;
}
node ans,a;
int x,y,n;
void init()
{
    memset(ans.a,0,sizeof(ans.a));
    memset(a.a,0,sizeof(a.a));
    for(int i=0;i<4;i++)
        ans.a[0][i]=1;
    a.a[0][0]=1;
    a.a[1][0]=1;a.a[1][1]=(x*x)%mod;a.a[1][2]=1;a.a[1][3]=x;
    a.a[2][1]=(y*y)%mod;//这里的%mod很有必要,不然下次乘的时候可能会超int,
    a.a[3][1]=(2*x*y)%mod;a.a[3][3]=y;
}
void pow1(int k)
{
    init();
    while(k)
    {
        if(k%2)ans=ans*a;
        a=a*a;
        k=k>>1;
    }
    printf("%d\n",ans.a[0][0]);
}
int main()
{
    while(~scanf("%d%d%d",&n,&x,&y))
    {
        x%=mod;
        y%=mod;
        pow1(n);
    }
}

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值