[ 欧拉定理 矩阵快速幂 ] BZOJ5118

来源:互联网 发布:女士电脑双肩包 知乎 编辑:程序博客网 时间:2024/05/21 23:32

如果直接用矩阵快速幂,复杂度是 O(n) 的。
因为1125899839733759是质数,所以可以用欧拉定理,求出 2n1 mod 1125899839733758 就好了。
时间复杂度 O(T23logn)

#include<bits/stdc++.h>using namespace std;#define ll long longconst ll M=1125899839733759;inline void Add(ll& x,ll y){    x=(x+y)%M;}inline ll Mul(ll x,ll y,ll MOD){    return ((x*y-(ll)(((long double)x*y+0.5)/MOD)*MOD)%MOD+MOD)%MOD;}inline ll Pow(ll x,ll y,ll p){    ll Ans=1;    for(;y;y>>=1,x=Mul(x,x,p))if(y&1)Ans=Mul(Ans,x,p);    return Ans;}struct Jz{    ll a[3][3];    Jz operator * (Jz b)const{        Jz c;        memset(c.a,0,sizeof(c.a));        for(int i=1;i<=2;i++)        for(int j=1;j<=2;j++)        for(int k=1;k<=2;k++)        Add(c.a[i][j],Mul(a[i][k],b.a[k][j],M));        return c;    }}a,b;inline Jz Pow(Jz x,ll y){    Jz Ans;    memset(Ans.a,0,sizeof(Ans.a));    Ans.a[1][1]=Ans.a[2][2]=1;    for(;y;y>>=1,x=x*x)if(y&1)Ans=Ans*x;    return Ans;}ll n;int i,j,k,m,p,T;int main(){    scanf("%d",&T);    while(T--){        scanf("%lld",&n);        memset(a.a,0,sizeof(a.a));a.a[1][1]=1;        b.a[1][1]=b.a[1][2]=b.a[2][1]=1;b.a[2][2]=0;        n=Pow(2,n,M-1)-1;if(n<0)n+=M-1;        a=a*Pow(b,n);        printf("%lld\n",a.a[1][1]);    }    return 0;}
阅读全文
0 0