I - 快来快来数一数 FZU - 2198(矩阵快速幂+预处理)



   n个六边形排成一行,相邻两个六边形共用一条边,如下图所示:




   记这个图形的生成树个数为t(n)(由于每条边都是不同的,不存在同构的问题)。那么t(1)=6,t(2)=35……

给出n,求mod 1000000007
Input

第一行给出数据组数T。

之后每一行给出一个正整数n。

T大约为50000,n<=10^18。
Output

每组数据输出一行答案。
Sample Input

2
2
12345678987654321

Sample Output

不太会。。。。。

# include <stdio.h>  
# include <algorithm>  
# include <string.h>  
# include <math.h>  
using namespace std;  
struct node  
{  
    __int64 m[3][3];  
};  
const __int64 mod=1000000007;  
node f(node a,node b)  
{  
    int i,j,k;  
    node c;  
    for(i=0; i<3; i++)  
        for(j=0; j<3; j++)  
        {  
            c.m[i][j]=0;  
            for(k=0; k<3; k++)  
            {  
                c.m[i][j]=(c.m[i][j]+((a.m[i][k]*b.m[k][j]))+mod)%mod;  
                //c.m[i][j]%=mod;  
            }  
        }  
    return c;  
}  
node quick(node origin,__int64 n)  
{  
  
    node answ;  
    memset(answ.m,0,sizeof(answ));  
    for(int i=0; i<3; i++)  
        answ.m[i][i]=1;  
    while(n)  
    {  
        if(n%2==1)  
        {  
            answ=f(origin,answ);  
  
        }  
        origin=f(origin,origin);  
        n/=2;  
    }  
    return answ;  
}  
  
int main()  
{  
  
  
    int t;  
    __int64 n;  
    node o,answ;  
    memset(o.m,0,sizeof(o.m));  
    o.m[0][0]=6;  
    o.m[0][1]=1;  
    o.m[1][0]=-1;  
    o.m[2][0]=1;  
    o.m[2][2]=1;  
  
    memset(answ.m,0,sizeof(answ.m));  
    answ.m[0][0]=7;  
    answ.m[0][1]=1;  
    answ.m[0][2]=1;  
  
    node hehe[80];  
    hehe[1]=o;  
    for(int i=2; i<70; i++)//预处理  
    {  
        hehe[i]=f(hehe[i-1],hehe[i-1]);  
    }  
    while(~scanf("%d",&t))  
    {  
        while(t--)  
        {  
            scanf("%I64d",&n);  
            if(n==1)  
                printf("6\n");  
            else if(n==2)  
                printf("41\n");  
            else  
            {  
                node B;  
                memset(B.m,0,sizeof(B.m));  
                n--;  
                for(int i=0; i<3; i++)  
                    B.m[i][i]=1;  
                for (int i = 1; n; i++, n >>= 1)  
                {  
                    if (n&1)  
                        B=f(B, hehe[i]);  
                }  
                node t=f(answ,B);  
                printf("%I64d\n",(t.m[0][0]-1+mod)%mod);  
            }  
        }  
    }  
    return 0;  
}  



   41
733521876

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值