HDU2256(矩阵快速幂)

题目

http://acm.hdu.edu.cn/showproblem.php?pid=2256

  • Problem Description
    在这里插入图片描述

  • Input
    The first line of input gives the number of cases, T. T test cases follow, each on a separate line. Each test case contains one positive integer n. (1 <= n <= 109)

  • Output
    For each input case, you should output the answer in one line.

  • Sample Input
    3
    1
    2
    5

  • Sample Output
    9
    97
    841

题意

计算如图所示的式子

思路

推到答案和n的关系
原 式 ( 2 + 3 ) 2 n = ( 5 + 2 6 ) n . 原式(\sqrt{2}+\sqrt{3})^{2n} = (5+2\sqrt{6})n. (2 +3 )2n=(5+26 )n.

令 ( 5 + 2 6 ) n = A n + B n 6 . 令(5+2\sqrt{6})^n = A_n +B_n\sqrt{6}. (5+26 )n=An+Bn6 .
A n + B n 6 = ( 5 + 2 6 ) ( A n − 1 + B n − 1 6 ) A_n +B_n\sqrt{6} = (5+2\sqrt{6})(A_{n-1} +B_{n-1}\sqrt{6}) An+Bn6 =(5+26 )(An1+Bn16 )
= ( 5 A n − 1 + 12 B n − 1 ) + ( 2 A n − 1 + 5 B n − 1 ) ∗ 6 . = (5A_{n-1}+12B_{n-1})+(2A_{n-1}+5B_{n-1})*\sqrt{6}. =(5An1+12Bn1)+(2An1+5Bn1)6 .

对 应 A n = 5 A n − 1 + 12 B n − 1 对应A_n=5A_{n-1}+12B_{n-1} An=5An1+12Bn1
B n = ( 2 A n − 1 + 5 B n − 1 ) ∗ 6 B_n=(2A_{n-1}+5B_{n-1})*\sqrt{6} Bn=(2An1+5Bn1)6
在这里插入图片描述
然后是Xn,Yn和答案的关系:
( 5 − 2 6 ) n = A n − B n 6 &lt; 1 (5-2\sqrt{6})^n = A_n -B_n\sqrt{6} &lt; 1 (526 )n=AnBn6 <1

a n s = A n + B n 6 + ( A n − B n 6 ) − ( A n − B n 6 ) ans = A_n +B_n\sqrt{6} + (A_n-B_n\sqrt{6}) - (A_n -B_n\sqrt{6}) ans=An+Bn6 +(AnBn6 )(AnBn6 )
= 2 A n − ( A n − B n 6 ) =2A_n - (A_n -B_n\sqrt{6}) =2An(AnBn6 )

2 A n − ( A n − B n 6 ) 取 整 为 2 A n − 1 2A_n - (A_n -B_n\sqrt{6}) 取整为 2A_n - 1 2An(AnBn6 )2An1
即 a n s = 2 A n − 1 即ans = 2A_n - 1 ans=2An1

矩阵快速幂

和快速幂唯一的区别是 整数 相乘变成了 矩阵相乘

代码

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int MOD = 1024;

struct matrix {
    ll m[3][3];

    matrix friend operator *(matrix a,matrix b) {
        matrix c;
        for(int i=1; i<=2; i++)
            for(int j=1; j<=2; j++)
                c.m[i][j]=0;

        for(int i=1; i<=2; i++)
            for(int j=1; j<=2; j++)
                for(int k=1; k<=2; k++)
                    c.m[i][j] = (c.m[i][j]+a.m[i][k]*b.m[k][j])%MOD;
        return c;
    }

} Rematrix,ansmatrix;

matrix m_pow(matrix a,int b) {
	matrix ans;
    ans.m[1][1]=ans.m[2][2]=1;
    ans.m[1][2]=ans.m[2][1]=0;
    while(b) {
        if(b & 1)
            ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}

int main() {
    int N;
    scanf("%d",&N);
    int n;
    Rematrix.m[1][1]=5;
    Rematrix.m[1][2]=12;
    Rematrix.m[2][1]=2;
    Rematrix.m[2][2]=5;

	long long ans=0;
    for(int i=1; i<=N; ++i) {
        scanf("%d",&n);
		ansmatrix = m_pow(Rematrix,n-1);
		ans = (5*ansmatrix.m[1][1] + 2*ansmatrix.m[1][2])%MOD ;
		printf("%lld\n",(2*ans-1+MOD)%MOD);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值