HDU6050 Funny Function

題目連接

題意

​ 已知 F1,1=F1,2=1

F1,i=F1,i1+2F1,i2

Fi,j=j+N1k=jFi1,k

​ 給出N,M,求 FM,1

分析

​ 看了官方題解才搞定的T_T,真是太菜了。

​ 可以通過歸納法發現 Fi,j=Fi,j1+2Fi,j2(j3) (最重要的推論=-=)

​ 拆解合並可以發現 jk=1Fi,k=Fi,j+1Fi,1 (j爲偶數),jk=1Fi,k=Fi,j+1Fi,2+Fi,1 (j爲奇數)。同時Fi,k=ai,kFi,2+bi,kFi,1

​ 再然後就是題解中寫到的,

N爲偶數時:(Fi,1,Fi,2)=(Fi1,n+1Fi1,1,Fi1,n+2Fi1,2)

=(Fi1,n+1,Fi1,n+2)+(Fi1,1,Fi1,2)

=(Fi1,1,Fi1,2)An+(Fi1,1,Fi1,2)B1

=(Fi1,1,Fi1,2)(An+B1)

(Fm,1,Fm,2)=(Fi1,1,Fi1,2)(An+B1)m1

N爲奇數時:(Fi,1,Fi,2)=(Fi1,n+1Fi1,2+Fi1,1,Fi1,n+22Fi1,1)

=(Fi1,n+1,Fi1,n+2)+(Fi1,2+Fi1,1,2Fi1,1)

=(Fi1,1,Fi1,2)An+(Fi1,1,Fi1,2)B2

=(Fi1,1,Fi1,2)(An+B2)

(Fm,1,Fm,2)=(Fi1,1,Fi1,2)(An+B2)m1

推出 A,B1,B2 ,套一下矩陣快速冪即可。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
const int mod=1e9+7;
const long long N = 3;
LL t,b,c,f1,f2;
struct Node  {  //矩陣  
    long long line,cal;
    long long a[3][3];
    Node(){  
        line=3,cal=3;
        a[0][0] = 0; a[0][1] = 2; a[0][2] = 0;
        a[1][0] = 0; a[1][1] = 2; a[1][2] = 1;
        a[2][0] = 0; a[2][1] = 0; a[2][2] = -1;
    }
    friend Node operator+(Node &A,Node &B){
        Node ret;
        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
                ret.a[i][j]=((A.a[i][j]+B.a[i][j])%mod+mod)%mod;
        return ret;
    }
}I,B1,B2;
Node Matlab(Node x,Node s)  {  //矩陣乘法
    Node ans;  
    ans.line = x.line,ans.cal = s.cal;  
    memset(ans.a,0,sizeof(ans.a));
    for(long long i=0;i<x.line;i++)  {
        for(long long j=0;j<x.cal;j++)   {  
            if(x.a[i][j]!=0)
                for(long long k=0;k<s.cal;k++)  {
                            ans.a[i][k] += x.a[i][j]*s.a[j][k];
                            ans.a[i][k]=((ans.a[i][k]+mod)%mod+mod)%mod;
                      }
        }
    }
    return ans;  
}
Node Fast_Matrax(Node tmp,LL b)  {  //矩陣快速冪
    Node ans=I;
    while(b){
        if(b&1)
            ans=Matlab(ans,tmp);
        b>>=1;
        tmp=Matlab(tmp,tmp);
    }
    return ans;
}
int main()  {
    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j){
            if(i==j)
                I.a[i][j]=1;
            else
                I.a[i][j]=0;
            B1.a[i][j]=B2.a[i][j]=0;
        }
    B1.a[0][0]=-1;B1.a[0][1]=0;B1.a[0][2]=0;
    B1.a[1][0]=0;B1.a[1][1]=-1;B1.a[1][2]=0;
    B2.a[0][0]=1;B2.a[0][1]=-1;B2.a[0][2]=0;
    B2.a[1][0]=-2;B2.a[1][1]=0;B2.a[1][2]=0;
    int T;
    LL n,m;
    cin>>T;
    while(T--){
        cin>>n>>m;
        Node A,tmp,tmp2;
        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
                A.a[i][j]=0;
        if(n==1 || m==1){
            printf("1\n");
            continue;
        }
        tmp=Fast_Matrax(tmp,n-1);
        A.a[0][0]=((tmp.a[0][1]-tmp.a[0][2])%mod+mod)%mod;
        A.a[0][1]=((tmp.a[1][1]-tmp.a[1][2])%mod+mod)%mod;
        tmp=Node();
        tmp=Fast_Matrax(tmp,n);
        A.a[1][0]=((tmp.a[0][1]-tmp.a[0][2])%mod+mod)%mod;
        A.a[1][1]=((tmp.a[1][1]-tmp.a[1][2])%mod+mod)%mod;
        if(n&1)
            A=A+B2;
        else
            A=A+B1;
        A=Fast_Matrax(A,m-1);
        LL ans=((A.a[0][0]+A.a[0][1])%mod+mod)%mod;
        cout<<ans<<endl;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章