【洛谷T37388】P哥破解密码

原题图:

 

 看到这个题,首先想到的当然是暴力打表找规律了

表:

1  2

2  4

3  7

4  13

5  24

6  44

7  81

8  149

9  274

10  504

11  927

12  1705

13  3136

14  5768

15  10609

发现上下两个数近似于2倍关系,但f[i-1]*2略大于f[i]

用f[i-1]*2-f[i],发现恰好等于f[i-4]

于是就有了递推式:f[i]=f[i-1]*2-f[i-4]

矩阵加速即可

矩阵加速的方法:

我们有一个4*4的矩阵A和一个向量c[13,7,4,2],

我们要让c*A得到向量c1[13*2-2,13,7,4]

于是得到下面的矩阵:

2  1  0  0
0  0  1  0
0  0  0  1
-1 0  0  0

矩阵快速幂即可

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MOD 19260817
#define int long long
int T,n,ans[5]={0,2,4,7,13};
struct Matrix{
    int m[5][5];
} O,E,A;
inline Matrix Mul(Matrix X,Matrix Y){
    Matrix Ans=O;
    for(int i=1;i<=4;i++)
     for(int j=1;j<=4;j++)
      for(int k=1;k<=4;k++)
       Ans.m[i][j]=(Ans.m[i][j]+X.m[i][k]*Y.m[k][j])%MOD;
    return Ans;
}
Matrix qpow(Matrix X,int k){
    Matrix S=E;
    while(k){
        if(k&1) S=Mul(S,X);
        k>>=1;
        X=Mul(X,X);
    }
    return S;
}
#undef int
int main()
#define int long long
{
    E.m[1][1]=E.m[2][2]=E.m[3][3]=E.m[4][4]=1;
    A.m[1][1]=2;
    A.m[1][2]=1;
    A.m[2][3]=1;
    A.m[4][1]=-1;
    A.m[3][4]=1;
    scanf("%lld",&T);
    for(int i=1;i<=T;i++){
        scanf("%lld",&n);
        if(n<=4){
            printf("%lld\n",ans[n]);
            continue;
        }
        Matrix Ans=qpow(A,n-4);
        int ans=((Ans.m[1][1]*13+Ans.m[2][1]*7+Ans.m[3][1]*4+Ans.m[4][1]*2)%MOD+MOD)%MOD;
        printf("%lld\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/yjkhhh/p/9414358.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值