2019牛客暑期多校训练营(第五场)B:generator 1 (10进制快速幂)

题意:给定x0,x1,a,b,满足xi=a*xi-1+b*xi-2; 求xn,n<10^(10^6);

思路:10进制快速幂裸题。降幂来写好像也是可以的,但是循环节不是phi(mod),所以数学不好就还是用10进制快速幂吧。

10进制快速幂:复杂度O(n*log10*K^3); 复杂度也不低,所以要尽量少做mod运算。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll Mod;
inline ll mul(ll x,ll y,ll p){
  return x*y%p;
}
struct mat
{
    ll M[3][3];
    mat() { M[1][1]=M[1][2]=M[2][1]=M[2][2]=0; }
    mat friend operator *(mat a,mat b)
    {
        mat res;
        for(int k=1;k<=2;k++)
         for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
           res.M[i][j]+=a.M[i][k]*b.M[k][j];//每次取mod复杂度会过高。
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
           res.M[i][j]%=Mod;
        return res;
    }
    mat friend operator ^(mat a,int x)
    {
       mat res; res.M[1][1]=res.M[2][2]=1LL;
       while(x){
          if(x&1) res=res*a; a=a*a; x/=2;
       } return res;
    }
};
char c[1000010];int x[1000010];
int main()
{
    int T; ll X0,X1,A,B,N;
    T=1;
    while(T--){
        scanf("%lld%lld%lld%lld",&X0,&X1,&A,&B);
        scanf("%s%lld",c+1,&Mod);
        int len=strlen(c+1);
        for(int i=1;i<=len;i++) x[i]=c[i]-'0';
        x[len]--;
        for(int i=len;i>=1;i--){
            if(x[i]<0) x[i-1]--,x[i]+=10;
        }
        mat base,a,ans;
        ans.M[1][1]=ans.M[2][2]=1;
        base.M[1][1]=A%Mod; base.M[1][2]=B%Mod; base.M[2][1]=1LL;
        a.M[1][1]=X1%Mod,a.M[2][1]=X0%Mod;
        for(int i=len;i>=1;i--){
             if(x[i]) ans=ans*(base^x[i]);
             base=base^10;
        }
        ans=ans*a;
        printf("%lld\n",ans.M[1][1]%Mod);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/11287817.html