hdu 6050 Funny Function

来源:互联网 发布:淘宝售后客服术语大全 编辑:程序博客网 时间:2024/05/01 15:01
 /*  打表找到公式,矩阵快速幂加速- -  马虎:ll 类型  写成int , 一直 wrong T.T  1-7^n / 1-7 f(n) =2^(n-1)+f(n-2) */ #include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;typedef long long ll;const int mod =1e9+7;struct mex{    int a[4][4];}m1[6];mex Plus(mex a,mex b){    mex c;ll d;    memset(c.a,0,sizeof(c.a));    for(int i=1;i<=3;++ i)     for(int j=1;j<=3;++ j)      for(int k=1;k<=3; ++ k)        {                        d=a.a[i][k];            d *=b.a[k][j];            d %=mod;            c.a[i][j] =(c.a[i][j]+d)%mod;        }      return c;}ll quickm(ll n,ll m)  {      ll a=1,x=n;      while(m)      {          if(m&1) a =(a*x)%mod;          x=(x*x)%mod;          m /=2;      }      return a%mod;  }  void gcd(ll a,ll b,ll &d,ll &x,ll &y)  {      if(!b) {d=1;x=1;y=0;}      else      {          gcd(b,a%b,d,y,x); y-= x*(a/b);      }  }  int inc(int a,int mod)  {      ll x,y,d;      gcd(a,mod,d,x,y);      return d==1?(x+mod)%mod:-1;  }void init(){    m1[1].a[1][1]=1;    m1[1].a[2][1]=4;    m1[1].a[3][1]=2;    memset(m1[2].a,0,sizeof(m1[2].a));    m1[2].a[1][3]=1;m1[2].a[3][1]=1;m1[2].a[3][2]=1;    m1[2].a[2][2]=2;}int main(){    int t;    ll n,m;    scanf("%d",&t);    while(t--)    {        scanf("%lld%lld",&n,&m);        ll n0,nn=n;        if(m==1||n==1) { printf("1\n"); continue;}        init();        n0=n-1;n -=2;        while(n)        {                            if(n&1) m1[1]=Plus(m1[2],m1[1]);            m1[2]=Plus(m1[2],m1[2]);            n /=2;        }        int a1=m1[1].a[3][1],a0=0;        if(n0==1) a0=1;        if(!a0)        {            n=n0;n -=2;            init();            while(n)           {              if(n&1) m1[1]=Plus(m1[2],m1[1]);                            m1[2]=Plus(m1[2],m1[2]);              n /=2;           }           a0=m1[1].a[3][1];        }        if(m==2)         {            printf("%d\n",a1);            continue;         }        int dos=(a0+a1)%mod;        ll d=quickm(dos,m-2);        ll ans=(ll)d*a1%mod;        if(nn%2)        {            int ink=inc(dos-1,mod);                     ll dd =ink;dd *=d-1; dd%=mod; dd *=a0;dd %=mod;            ans -=dd;            ans =(ans+mod)%mod;        }        printf("%lld\n",ans);    }    return 0;}