2017 Multi-University Training Contest 10 1002 Array Challenge HDU 6172(找规律 矩阵快速幂)

题意:There’s an array that is generated by following rule.
h0=2,h1=3,h2=6,hn=4hn1+17hn212hn316
And let us define two arrays  bnandan  as below.
bn=3hn+1hn+9hn+1hn1+9h2n+27hnhn118hn+1126hn81hn1+192(n>0)
an=bn+4n
Now, you have to print  (an)  , n>1.

Your answer could be very large so print the answer modular 1000000007.


思路:这规律都能找到。。。也是厉害的。。。

摘自博客:点击打开链接

解题思路: fn=an ,写出前几项 f2=31,f3=197,f4=1255,f5=7997,f6=50959  
h3=35,h4=190,h5=1267,h6=7862  
可以发现 fn hn 的递推结果很像, 
于是根据 hn 的递推关系猜测 fn=4fn1+17fn212fn3  
是一个线性递推式,用矩阵快速幂。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
struct node
{
    ll s[5][5];
};

node mul(node a, node b)
{
    node t;
    memset(t.s, 0, sizeof(t.s));
    for(int i = 1; i <= 3; i++)
        for(int j = 1; j <= 3; j++)
            for(int k = 1; k <= 3; k++)
                t.s[i][j] = (t.s[i][j]+a.s[i][k]*b.s[k][j]+mod)%mod;
    return t;
}

node mt_pow(node p, ll q)
{
    node res;
    memset(res.s, 0, sizeof(res.s));
    for(int i = 1; i <= 3; i++) res.s[i][i] = 1;
    while(q)
    {
        if(q%2) res = mul(res, p);
        p = mul(p, p);
        q /= 2;
    }
    return res;
}

int main(void)
{
    int t;
    cin >> t;
    while(t--)
    {
        ll n;
        scanf("%lld", &n);
        if(n == 2) puts("31");
        else if(n == 3) puts("197");
        else if(n == 4) puts("1255");
        else if(n == 5) puts("7997");
        else
        {
            node base;
            memset(base.s, 0, sizeof(base.s));
            base.s[1][1] = 4, base.s[1][2] = 17, base.s[1][3] = -12;
            base.s[2][1] = 1, base.s[3][2] = 1;
            node ans = mt_pow(base, n-4);
            ll res = (ans.s[1][1]*1255%mod+ans.s[1][2]*197%mod+ans.s[1][3]*31%mod+mod)%mod;
            printf("%lld\n", res);
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值