ACM-ICPC 2018 Jiaozuo Cyber ​​Preliminaries L Poor God Water (BM Algorithm)

God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him that some sequence of eating will make them poisonous.

Every hour, God Water will eat one kind of food among meat, fish and chocolate. If there are 3 continuous hours when he eats only one kind of food, he will be unhappy. Besides, if there are 3 continuous hours when he eats all kinds of those, with chocolate at the middle hour, it will be dangerous. Moreover, if there are 3 continuous hours when he eats meat or fish at the middle hour, with chocolate at other two hours, it will also be dangerous.

Now, you are the doctor. Can you find out how many different kinds of diet that can make God Water happy and safe during N hours? Two kinds of diet are considered the same if they share the same kind of food at the same hour. The answer may be very large, so you only need to give out the answer module 1000000007.

Input

The fist line puts an integer T that shows the number of test cases. (T≤1000)

Each of the next TT lines contains an integer N that shows the number of hours. (1≤N≤10^10)

Output

For each test case, output a single line containing the answer.

样样

3
3
4
15

样样

20
46
435170

In the condition of meeting all the conditions, the table was obtained, the first 20 sets of data, emmmm, and then tried to test the BM template of Du Jiao, I did not expect to pass once, I can think of BM algorithm is enough for me to show, write times = This blog, as a template for BM.

Code implementation (templates for teammates to change hard):
/****
***author: winter2121
****/
#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define SI(i) scanf("%d",&i)
#define PI(i) printf("%d\n",i)
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int MAX=1e6+5;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
int dir[9][2]={0,1,0,-1,1,0,-1,0, -1,-1,-1,1,1,-1,1,1};
template<class T>bool gmax(T &a,T b){return a<b?a=b,1:0;}
template<class T>bool gmin(T &a,T b){return a>b?a=b,1:0;}
template<class T>void gmod(T &a,T b){a=((a+b)%mod+mod)%mod;}

ll gcd(ll a,ll b){ while(b) b^=a^=b^=a%=b; return a;}
ll inv(ll b){return b==1?1:(mod-mod/b)*inv(mod%b)%mod;}
ll qpow(ll n,ll m)
{
    n%=mod;
    ll ans=1;
    for(;m;m>>=1)
    {
        if(m&1)ans=ans*n%mod;
        n=n*n%mod;
    }
    return ans;
}


struct linear_seq {
    static const int MAX=10005;
    ll res[MAX],base[MAX],cao[MAX],nmd[MAX];
    vector<int> Md;
    void mul(ll a[],ll b[],int k) {
        for(int i=0;i<k+k;i++)
            cao[i]=0;
        for(int i=0;i<k;i++) if(a[i])
            for(int j=0;j<k;j++)
                cao[i+j]=(cao[i+j]+a[i]*b[j])%mod;
        for (int i=k+k-1;i>=k;i--) if (cao[i])
            for(int j=0;j<Md.size();j++)
                cao[i-k+Md[j]]=(cao[i-k+Md[j]]-cao[i]*nmd[Md[j]])%mod;
        for(int i=0;i<k;i++)
            a[i]=cao[i];
    }
    int solve(ll n,vector<int> a,vector<int> b) {
        ll ans=0,pnt=0;
        int k=a.size();
        for(int i=0;i<k;i++)
            nmd[k-1-i]=-a[i];nmd[k]=1;
        Md.clear();
        for(int i=0;i<k;i++) if (nmd[i]!=0) Md.push_back(i);
        for(int i=0;i<k;i++)
            res[i]=base[i]=0;
        res[0]=1;
        while ((1ll<<pnt)<=n) pnt++;
        for (int p=pnt;p>=0;p--) {
            mul(res,res,k);
            if ((n>>p)&1) {
                for (int i=k-1;i>=0;i--)
                    res[i+1]=res[i];res[0]=0;
                for(int j=0;j<Md.size();j++)
                    res[Md[j]]=(res[Md[j]]-res[k]*nmd[Md[j]])%mod;
            }
        }
        for(int i=0;i<k;i++)
            ans=(ans+res[i]*b[i])%mod;
        if (ans<0)
            ans+=mod;
        return ans;
    }
    vector<int> yuchuli(vector<int> s) {
        vector<int> C(1,1),B(1,1);
        int L=0,m=1,b=1;
        for(int n=0;n<s.size();n++){
            ll d=0;
            for(int i=0;i<=L;i++)
                d=(d+(ll)C[i]*s[n-i])%mod;
            if (d==0) m++;
            else if (2*L<=n) {
                vector<int> T=C;
                ll c=mod-d*qpow(b,mod-2)%mod;
                while (C.size()<B.size()+m) C.push_back(0);
                for(int i=0;i<B.size();i++)
                    C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                ll c=mod-d*qpow(b,mod-2)%mod;
                while (C.size()<B.size()+m) C.push_back(0);
                for(int i=0;i<B.size();i++)
                    C[i+m]=(C[i+m]+c*B[i])%mod;
                m++;
            }
        }
        return C;
    }
    int getseq(vector<int> a,ll n) {
        vector<int> c=yuchuli(a);
        c.erase(c.begin());
        for(int i=0;i<c.size();i++)
            c[i]=(mod-c[i])%mod;
        int ans=solve(n,c,vector<int>(a.begin(),a.begin()+c.size()));
        return ans;
    }
}seq;

int main() {
    int T;
    ll n;
    cin>>T;
    while(T--)
    {
        vector<int>v({20,46,106,244,560,1286,2956,6794,15610,35866,82416,189384,435170,999936,2297686});
        scanf("%lld",&n);
        ll ans=3;
        if(n==1)ans=3;
        else if(n==2)ans=9;
        else ans=seq.getseq(v,n-3);
        printf("%lld\n",ans);
    }
}