HDU6050: Funny Function(推公式+矩阵快速幂)

传送门

题意

利用给出的式子求(F_{m,1})

分析

直接推公式(都是找规律大佬)
(n为偶数,F_{m,1}=frac{2(2^n-1)^{m-1}}3)
(n为奇数,F_{m,1}=F_{m-1,1}(2^n-1)-frac{2(4^{frac n2}-1)}3)
抱歉啊,markdown矩阵相乘实在调不出来了,勉强看一看吧QAQ
( left[ egin{matrix} 2^n-1&-1 \ 0&1 end{matrix} ight] ag{3} )
( left[ egin{matrix} F_{m-1,1} \ frac{2(4^{frac n2}-1)}3 end{matrix} ight] ag{3} ) (=) ( left[ egin{matrix} F_{m,1}\ frac{2(4^{frac n2}-1)}3 end{matrix} ight] ag{3} )

做一次矩阵快速幂即可

trick

m为1,n为偶数直接输出1

代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
const int N = 2;
const ll mod = 1e9+7;
int t;
ll n,m,n_2,n_4,ni_3;
struct matrix
{
    ll mp[N][N];
    matrix()
    {
        mem(mp,0);
    }
};

ll pow_mod(ll a,ll p)
{
    ll ans=1;
    for(ll ret=a%mod;p;p>>=1,ret=ret*ret%mod) if(p&1) ans=ans*ret%mod;
    return ans;
}
matrix mul(matrix a,matrix b)//矩阵相乘
{
    matrix ans;
    R(i,0,2)R(j,0,2)R(k,0,2) (ans.mp[i][j]+=a.mp[i][k]*b.mp[k][j]%mod)%=mod;
    return ans; 
}
matrix matrix_pow_mod(matrix a,ll p)
{
    matrix ans,ret;
    R(i,0,2)R(j,0,2) ret.mp[i][j]=a.mp[i][j];
    ans.mp[0][0]=ans.mp[1][1]=1;
    while(p)
    {
        if(p&1) ans=mul(ans,ret);
        ret=mul(ret,ret);
        //R(i,0,2)R(j,0,2) printf("%I64d%c", ret.mp[i][j],j==1?'
':' ');
        p>>=1;
    }
    return ans;
}
void init()
{
    n_2=(pow_mod(2LL,(ll)n)-1+mod)%mod;//求2^n-1
    n_4=(pow_mod(4LL,(ll)(n/2))-1+mod)%mod;//求4^n-1
    ni_3=pow_mod(3LL,mod-2);//求3的逆元
    n_4=n_4*2%mod*ni_3%mod;
}

void work1()
{
    matrix temp,ret;
    temp.mp[0][0]=n_2,temp.mp[0][1]=-1;
    temp.mp[1][0]=0,temp.mp[1][1]=1;
    ret=matrix_pow_mod(temp,(ll)(m-1));//矩阵快速幂
    ll ans=0;
    //R(i,0,2)R(j,0,2) printf("%I64d
",ret.mp[i][j] );
    ans=(ret.mp[0][0]+ret.mp[0][1]*n_4%mod+mod)%mod;
    while(ans<0) ans+=mod;
    printf("%I64d
",ans );
}

void work2()
{
    ll ans=pow_mod(n_2,(ll)(m-1));
    ans=ans*2%mod*ni_3%mod;
    ans=(ans+mod)%mod;
    printf("%I64d
",ans );
}

int main()
{
    for(scanf("%d",&t);t--;)
    //F(i,1,10)F(j,1,10)
    {
        scanf("%lld %lld",&n,&m);
        //n=i,m=j;printf("n=%I64d m=%I64d
",n,m );
        init();
        if(m==1) { puts("1");continue; }
        if(n&1) work1();else work2();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chendl111/p/7272989.html