1. 程式人生 > >HDU2256&&HDU4565:給一個式子的求第n項的矩陣快速冪

HDU2256&&HDU4565:給一個式子的求第n項的矩陣快速冪

升級版本 簡單 eof ems size lan blank 向下取整 c++

HDU2256

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2256

題意:求(sqrt(2)+sqrt(3))^2n%1024是多少。

這個題算是hdu4565的一個常數版本了,所以我們先說這道題。對於這道題的做法我們可以計算((sqrt(2)+sqrt(3))^2)^n=(5+2*sqrt(6))^n,對於(5+2*sqrt(6))^n我們知道答案必定是以an+bn*sqrt(6),而對於下一項我們只需要求(an+bn*sqrt(6))*(5+2*sqrt(6))=5*an+12*bn+2*an*sqrt(6)+5*bn*sqrt(6),所以a(n+1)=5*an+12*bn; b(n+1)=2*an+5*bn。有了這個遞推式我們就可以構造矩陣求an,bn。

這裏還有一點對於(5+2*sqrt(6))^n=an+bn*sqrt(6); 同理(5-2*sqrt(6))^n=an-bn*sqrt(6);兩式相加(5+2*sqrt(6))^n+(5-2*sqrt(6))^n=2*an,當n趨於無窮的時候lim(5-2*sqrt(6))^n=0,因為5-2*sqrt(6)<1。

所以我們可以得到答案(5+2*sqrt(6))^n約等於2*an,且實際值是比2*an要小的且小於2*an-1要大的,所以由題目的意思我們向下取整,ans=2*an-1;具體看代碼,其他都是矩陣快速冪的模板。

//Author: xiaowuga
#include <bits/stdc++.h>
#define
maxx INT_MAX #define minn INT_MIN #define inf 0x3f3f3f3f #define n 2 #define MOD 1024 using namespace std; typedef long long ll; struct Matrix{ ll mat[4][4]; Matrix operator * (const Matrix & m) const{ Matrix tmp; for(int i=0;i<n;i++) for(int j=0;j<n;j++){ tmp.mat[i][j]
=0; for(int k=0;k<n;k++){ tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD; tmp.mat[i][j]%=MOD; } } return tmp; } }; Matrix POW(Matrix &m,int k){ Matrix ans; memset(ans.mat,0,sizeof(ans.mat)); for(int i=0;i<n;i++) ans.mat[i][i]=1; while(k){ if(k&1) ans=ans*m; k/=2; m=m*m; } return ans; } int main() { ios::sync_with_stdio(false);cin.tie(0); ll T,num; cin>>T; while(T--){ cin>>num; Matrix m; m.mat[0][0]=5; m.mat[0][1]=12; m.mat[1][0]=2; m.mat[1][1]=5; Matrix ans=POW(m,num-1); ll sum=0,f[2]={5,2}; for(int i=0;i<2;i++) sum+=ans.mat[0][i]*f[i]%MOD; sum%=MOD; ll x=(2*sum-1)%MOD; cout<<x<<endl; } return 0; }

HDU4565

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4565

題意:算是上面那道題的一個升級版本啦。現在是a和b不是固定的的常數了。和上面的做法一樣。註意題目中給出a-sqrt(b)<1的條件,所以基本和上道題是一樣的了,類比一下吧!很簡單的。但是這裏是向上取整,所以答案是2*an。具體看代碼吧。由於上面那道題在常數情況下已經說得很明白了。這道題就不說了

//Author: xiaowuga
#include <bits/stdc++.h>
#define maxx INT_MAX
#define minn INT_MIN
#define inf 0x3f3f3f3f
#define size 2
int MOD;
using namespace std;
typedef long long ll;
struct Matrix{
    ll mat[4][4];
    void clear(){
        memset(mat,0,sizeof(mat));
    }
    Matrix operator * (const Matrix & m) const{
        Matrix tmp;
        for(int i=0;i<size;i++)
            for(int j=0;j<size;j++){
                tmp.mat[i][j]=0;
                for(int k=0;k<size;k++){
                    tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD;
                    tmp.mat[i][j]%=MOD;
                }
            }
        return tmp;
    }
};
Matrix POW(Matrix &m,int k){
    Matrix ans;
    memset(ans.mat,0,sizeof(ans.mat));
    for(int i=0;i<size;i++) ans.mat[i][i]=1;
    while(k){
        if(k&1) ans=ans*m;
        k/=2;
        m=m*m;
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);
    ll  a,b,n;
    while(cin>>a>>b>>n>>MOD){
        Matrix m;
        m.clear();
        m.mat[0][0]=m.mat[1][1]=a%MOD;
        m.mat[0][1]=b%MOD;m.mat[1][0]=1;
        Matrix ans=POW(m,n-1);
        ll sum=(ans.mat[0][0]*a%MOD+ans.mat[0][1]%MOD)%MOD;
        cout<<2*sum%MOD<<endl;
    }
    return 0;
}

HDU2256&&HDU4565:給一個式子的求第n項的矩陣快速冪