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 

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;
}

 

你可能感兴趣的:(数学,矩阵快速幂)