Funny Function————(hdu6050)矩陣快速冪




這道題可以利用矩陣快速冪做 但是有些大神硬推公式就推出來了,佩服佩服
利用第一行F(1,k)推導可以發現當j爲奇數(F(i,1)+F(i,2)+……+F(i,j))=F(i,j+1)-F(i,2)+F(i,1);
當j爲偶數的時候(F(i,1)+F(i,2)+……+F(i,j))=F(i,j+1)-F(i,1);
當n爲偶數的時候我們進行(兩行爲一個矩陣運算)
{F(i,1)}={F(i-1,n+1)-F(i-1,1)}={F(i-1,n+1)}-{F(i-1,1)}
F(i,2) F(i-1,n+2)-F(i-1,2) F(i-1,n+2) - F(i-1,2)
{F(i-1,n+1)}={0 1}{F(i-1,n)} = {0 1}^n{F(i-1,1)}
F(i-1,n+2) 2 1 F(i-1,n+1 2 1 F(i-1,2)
{F(i,1)}=[{0 1}^n-{1 0}]{F(i-1,1)}
F(i,2) 2 1 0 1 F(i-1,2)
{F(i,1)}=[{0 1}^n-{1 0}]^(m-1){F(1,1)}
 F(i,2)    2 1     0 1         F(1,2)
同理n爲奇數的時候同理矩陣那個
{F(i,1)}=[{0 1}^n-{-1 1}]^(m-1){F(1,1)}
 F(i,2)    2 1      2 0         F(1,2)

然後直接快速冪
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;


typedef long long ll;
const ll mod=1e9+7;
struct matrix
{
    ll f[2][2];
};
matrix mul(matrix a,matrix b)
{
    matrix ans;
    memset(ans.f,0,sizeof(ans.f));
    for(int i=0; i<2; i++)
    {
        for(int j=0; j<2; j++)
        {
            for(int k=0; k<2; k++)
            {
                ans.f[i][j]=(ans.f[i][j]+a.f[i][k]*b.f[k][j]%mod)%mod;
            }
        }
    }
    return ans;
}
matrix pow(matrix a, ll p)
{
    matrix res;
    memset(res.f,0,sizeof(res.f));
    for(int i=0; i<2; i++)
        res.f[i][i]=1;
    while(p)
    {
        //cout<<"___"<<endl;
        if(p&1)
            res=mul(res,a);
        p>>=1;
        a=mul(a,a);
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    ll n,m;
    while(T--)
    {
        scanf("%lld%lld",&n,&m);
        //cout<<n<<" "<<m<<endl;
        if(n%2==1)
        {
            matrix a;
            a.f[0][0]=0;
            a.f[0][1]=1;
            a.f[1][0]=2;
            a.f[1][1]=1;
            a=pow(a,n);
            a.f[0][0]+=1;
            a.f[0][1]-=1;
            a.f[1][0]-=2;
            a=pow(a,m-1);
            printf("%lld\n",(a.f[0][0]+a.f[0][1])%mod);
        }
        else
        {
            matrix a;
            a.f[0][0]=0;
            a.f[0][1]=1;
            a.f[1][0]=2;
            a.f[1][1]=1;
            a=pow(a,n);
            a.f[0][0]-=1;
            a.f[1][1]-=1;
            a=pow(a,m-1);
            printf("%lld\n",(a.f[0][0]+a.f[0][1])%mod);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章