数学+矩阵快速幂 | 打表找规律+数学归纳

 

Funny Function

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

 

 

 

题意:通过给定的函数计算 F(m,1),结果模上 1e9+7

 

 

 

 

 

题解:(转自RedPolya

F1,1=F1,2=1
F1,i=F1,i−1+2F1,i−2|i>=3
Fi,j=∑j+N−1k=jFi−1,k
给定N,M,求Fm,1

首先昨天先写了几个,发现Fi,j=Fi,j−1+2Fi,j−2也是成立的,于是就有下面的:
Fi,j+1−Fi,j=2Fi,j−1
Fi,jFi,j−1=2Fi,j−2

Fi,3−Fi,2=2Fi,1
迭加得:
Fi,j+1−Fi,2=2∑j−1k=1Fi,k
Fi,j+1−Fi,1=Fi,1+Fi,2+...+Fi,j−1+A
这里
A=2Fi,2+Fi,3+...+Fi,j−1
j+1为奇数时
A=Fi,j

Fi,j+1−Fi,1=∑jk=1Fi,k
j+1为偶数时,
2Fi,j+Fi,j+1=Fi,j+2→Fi,j+1+Fi,1−Fi,2=∑k=jk=1Fi,k

n为偶数时
Fi,1=∑nk=1Fi−1,k=Fi−1,n+1−Fi−1,1

[Fi,j+1Fi,j]=[1120]⋅[Fi,jFi,j−1]


Fi,1=Fi−1,1⋅AnB0 A,B0为矩阵如上所述。
Fm,1=F1,1⋅(AnB0)m−1

同理n为奇数时一样,
Fm,1=F1,1⋅(AnB1)m−1
其中,

A=[1120]


n偶数

 

B=[1001]


n奇数

 

B=[012−1]

 

 

 

 

#include<cstdio> 
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
const ll P = 1000000007;
const int N=2;
ll n,m;

struct matrix{
    ll a[N][N];
    int row,col;
    matrix():row(N),col(N){memset(a,0,sizeof(a));}
    matrix(int x,int y):row(x),col(y){memset(a,0,sizeof(a));}
    ll* operator [] (int x){return a[x];}
    matrix operator * (matrix x){
        matrix tmp ;
        for (int i=0;i<=n+1;i++)
            for (int j=0;j<=n+1;j++){
                tmp[i][j]=0;
                for (int k=0;k<=n+1;k++)
                    tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j])%P;
            }
        return tmp;
    }   
    matrix operator - (matrix x){
        matrix tmp ;
        for (int i=0;i<=n+1;i++)
            for (int j=0;j<=n+1;j++){
                tmp[i][j]=a[i][j] - x[i][j] + P;
                tmp[i][j]%=P;
            }
        return tmp;
    }   
    void operator *= (matrix x){*this = *this * x;}
    matrix operator ^ (ll x){
        matrix ret;
        for (int i=0;i<=n+1;i++)ret[i][i]=1;
        matrix tmp = *this;
        for (;x;x>>=1,tmp*=tmp){if(x&1)ret *=tmp;}
        return ret;
    }
};

int main(){
    long long T,nn,mm;
    cin>>T;
    n=0;
    while(T--){
        scanf("%lld%lld",&nn,&mm);
        matrix A,B,ans;
        A[0][0]=1;A[0][1]=2;A[1][0]=1;A[1][1]=0;
        if(nn&1){
            B[0][0]=0;B[0][1]=2;
            B[1][0]=1;B[1][1]=-1;
        } else {
            B[0][0]=1;B[0][1]=0;
            B[1][0]=0;B[1][1]=1;
        }
        ans = ((A ^ nn) - B) ^ (mm-1);
        cout<<(ans[0][0])<<endl;
    }
    return 0;
}


然后用特征值算矩阵n次方,可以求得
Fm,1=(2n−1)m−1⋅23|n为偶数
Fm,1=(2n−1)m−1⋅2+13|n为奇数
除三要么用逆元,要么取模的时候先对3000000021取模,最后再对1000000007取模。
于是,

 

 

 

 

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

typedef long long ll;

const ll P = 3000000021LL;
const ll MOD = 1000000007;

ll pow(ll a,ll n){
    if(n==0) return 1LL;
    ll tmp = pow(a,n/2);
    if(n&1)
        return tmp*tmp%P*a%P;
    return tmp*tmp%P;
}

int main(){
    int T;
    ll n,m;
    cin>>T;
    while(T--){
        scanf("%lld%lld",&n,&m);
        ll t = pow(2LL,n);
        t = (t - 1) % P;
        t = pow(t,m-1);
        if(n&1) t = t * 2LL + 1;
        else t = t * 2LL;
        t /= 3LL;
        cout<<t%MOD<<endl;
    }
    return 0;
}

 

 

 


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值