2019牛客暑期多校訓練營(第五場)generator 1 (十進制優化矩陣快速冪)

題意:

給了遞推式,F[n]=a*F[n-1]+b*F[n-2] ,已知F[0] 和F[1],求F[n]

 

思路:

聽了出題人的講解,才知道矩陣快速冪還能這樣的優化!

我們保留這四個最基本的矩陣:Matrix^1Matrix^2Matrix^4Matrix^8

那麼怎麼進行十進制優化呢?

舉個例子:

比如:F[23],這個用十進制優化怎麼求?

我們可以用保留的矩陣Matrix^1*Matrix^2來拼出23的低位的3

那麼20怎麼算出來呢?
這時候,我們就先拼出個10來:我們先讓Matrix^1=Matrix^2*Matrix^8

這樣我們的Matrix^1實際上就是原來的Matrix^1^0,然後我們在用Matrix^1^0來更新Matrix^2Matrix^4Matrix^8。這樣就能通過這些來得到冪次是10~100的了。(真神奇)

 

代碼:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll mod;
char s[maxn];
struct Matrix
{
    ll a[2][2];
    Matrix(){
        memset(a,0,sizeof(a));
    }
    friend Matrix operator * (Matrix a, Matrix b)
    {
        Matrix tmp;
        for(int i=0;i<2;i++){
            for(int j=0;j<2;j++){
                for(int k=0;k<2;k++){
                    (tmp.a[i][j]+=(a.a[i][k]*b.a[k][j])%mod)%=mod;
                }
            }
        }
        return tmp;
    }
};
int main()
{
    ll x,y,a,b;
    scanf("%lld%lld%lld%lld",&x,&y,&a,&b);
    scanf("%s",s);
    scanf("%lld",&mod);
    int len=strlen(s);
    Matrix tmp[4],ans;
    tmp[0].a[0][0]=a;
    tmp[0].a[0][1]=b;
    tmp[0].a[1][0]=1;
    tmp[0].a[1][1]=0;
    tmp[1]=tmp[0]*tmp[0];
    tmp[2]=tmp[1]*tmp[1];
    tmp[3]=tmp[2]*tmp[2];
    ans.a[0][0]=ans.a[1][1]=1;
    for(int i=len-1;i>=0;i--){
        int x=s[i]-'0';
        for(int j=0;j<4;j++){
            if(x>>j&1){
                ans=ans*tmp[j];
            }
        }
        tmp[0]=tmp[1]*tmp[3];
        tmp[1]=tmp[0]*tmp[0];
        tmp[2]=tmp[1]*tmp[1];
        tmp[3]=tmp[2]*tmp[2];
    }
    printf("%lld\n",(ans.a[1][0]*y%mod+ans.a[1][1]*x%mod)%mod);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章