Math Problem 2017广西邀请赛 矩阵快速幂+递推

原题传送门
题解:首先蒟蒻不会推,然后oeis大法好,
f(n)=f(n-1)+5*f(n-2)+f(n-3)-f(n-4);
那么这个不就是矩阵快速幂了呀;

#include <bits/stdc++.h>
#define fio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define debug(x) cout << #x << ": " << x << endl;
#define debug1(x) cout<<x<<endl;
#define ll long long
#define ull unsigned long long
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#define mse(a,b) memset(a,b,sizeof a);
#define fro for
#define it int
#define pb push_back
using namespace std;
const int maxx=1e6+100;
const int mod=1e9+7;
//ll gcd(ll a,ll b){ while(b^=a^=b^=a%=b); return a;}
//ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
//inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
struct node
{
    ll ans[10][10];
}a;
void init()///初始化列出我们递推的矩阵
{
  mse(a.ans,0);
  a.ans[0][0]=a.ans[0][2]=1;
  a.ans[0][1]=5;
  a.ans[0][3]=-1;
  a.ans[1][0]=a.ans[2][1]=a.ans[3][2]=1;
}
node operator *(const node &a,const node &b)///矩阵乘法模板 重载*
{
    node pp;
    mse(pp.ans,0);
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        for(int k=0;k<4;k++)
    {
        pp.ans[i][j]=(pp.ans[i][j]+a.ans[i][k]*b.ans[k][j]%mod)%mod;
    }
    return pp;
}
node powr(node x,ll y)//矩阵快速幂模板
{
    node pp;
    mse(pp.ans,0);
    for(int i=0;i<4;i++)
        pp.ans[i][i]=1;
    while(y)
    {
        if(y&1) pp=pp*x;
        x=x*x;
        y>>=1;
    }
    return pp;
}
int main()
{
    ll n;
    node t;
    mse(t.ans,0);
    t.ans[0][0]=36;
    t.ans[1][0]=11;
    t.ans[2][0]=5;
    t.ans[3][0]=1;
    while(cin>>n)
    {
       init();
        if(n<=4)
            cout<<t.ans[4-n][0]<<endl;
            else
            {
            a=powr(a,n-4);
            a=a*t;///切记矩阵乘法前往别搞反了
            ll dou=(a.ans[0][0]+mod)%mod;
            cout<<dou<<endl;
            }

    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值