hihocoder#1605 : 小Hi的生成树计数(矩阵快速幂)

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

小Hi最近对生成树(包含所有顶点的联通无环子图。)非常的感兴趣,他想知道对于特定的简单平面无向图是不是存在求生成树个数的简单方法。

小Hi定义了这样的图:一个以{0,1,2……n}为顶点的图,顶点0与其他n个顶点直接相连,对于顶点i(1 ≤ i < n),顶点i与顶点i+1连有一条边。下面是小Hi画的图n=4的图:


请求出对于任意n,这样的图的生成树个数。

输入

多组数据,每组数据一行,包括一个整数n

30%的数据(1 ≤ n ≤ 100),组数不超过10组

70%的数据(1 ≤ n ≤ 1000000),组数不超过10组

100%的数据(1 ≤ n ≤ 1000000000),组数不超过10组

输出

每组数据输出一个行包括一个整数,代表了图的生成树个数(对1000000007取模)。

样例输入
2
样例输出
3
思路:F(n)=3*F(n-1)-F(n-2)。即矩阵快速幂。(注意:多组数据)

#include<bits/stdc++.h>
using namespace std;
const int MOD=1000000007;
struct lenka
{
    long long a[2][2];
};
lenka cla(const lenka& a,const lenka& b)
{
    lenka c;
    memset(c.a,0,sizeof c.a);
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            for(int k=0;k<2;k++)
            {
                c.a[i][j]+=(a.a[i][k]*b.a[k][j])%MOD;
                c.a[i][j]=(c.a[i][j]%MOD+MOD)%MOD;
            }
        }
    }
    return c;
}
long long POW(long long n)
{
    lenka res,a;
    memset(a.a,0,sizeof a.a);
    memset(res.a,0,sizeof res.a);
    a.a[0][0]=3,a.a[0][1]=1;
    a.a[1][0]=-1;
    res.a[0][0]=res.a[1][1]=1;
    while(n)
    {
        if(n&1)res=cla(res,a);
        a=cla(a,a);
        n/=2;
    }
    return ((3ll*res.a[0][0]%MOD+res.a[1][0]%MOD)%MOD+MOD)%MOD;
}
int main()
{
    long long  n;
    while(scanf("%lld",&n)!=EOF)
    {
        if(n==1)cout<<1<<endl;
        else cout<<POW(n-2)<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值