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

来源:互联网 发布:Json 大括号 编辑:程序博客网 时间:2024/06/06 18:33

时间限制: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;}


原创粉丝点击