将NN个点排列成一个圆形,中间放置一个点固定为根节点,问特殊生成树的种类数。
特殊生成树:除根节点以外,其他节点只能与自己左右节点相连,或与根节点相连。
p.s.若节点的左右节点为同一个节点,向左或向右连接视为不同的生成树。
由于种类数可能过大,对1,000,000,0071,000,000,007取模。
当N=3N=3时,所有生成树表示如下:
Input
多组数据,请输入要文件结束。
每组数据包含一个整数N(0<N<109)N(0<N<109)。
Output
对于每组数据,输出一个整数,表示特殊生成树的种类数,答案对1,000,000,0071,000,000,007取模。
Example
Input
2 3
Output
5 16
由于此题数据较大要用到矩阵快速幂
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
struct juzhen
{
ll data[3][3];
};
juzhen mul(juzhen a,juzhen b)
{
juzhen c;
memset(c.data,0,sizeof(c.data));
for(int k=0;k<3;k++)
{
for(int i=0;i<3;i++)
{
if(!a.data[i][k]) continue;
for(int j=0;j<3;j++)
{
if(!b.data[k][j]) continue;
c.data[i][j]=(c.data[i][j]+a.data[i][k]*b.data[k][j]%mod)%mod;
}
}
}
return c;
}
juzhen mat_pow(juzhen a,ll n)
{
juzhen res;
memset(res.data,0,sizeof(res.data));
res.data[0][0]=res.data[1][1]=res.data[2][2]=1;
while(n)
{
if(n&1) res=mul(res,a);
a=mul(a,a);
n>>=1;
}
return res;
}
int main()
{
juzhen a;
memset(a.data,0,sizeof(a.data));
a.data[0][0]=3;
a.data[0][2]=a.data[1][0]=a.data[2][2]=1;
a.data[0][1]=-1;
ll n;
while(cin>>n)
{
if(n==1)
{
cout<<1<<endl;
continue;
}
juzhen ans;
ans=mat_pow(a,n-2);
juzhen g;
g.data[0][0]=5;
g.data[1][0]=1;
g.data[2][0]=2;
juzhen res;
res=mul(ans,g);
cout<<(res.data[0][0]+mod)%mod<<endl;//就是这个地方
}
return 0;
}
//3 -1 1 f(n-1)
//1 0 0 f(n-2)
//0 0 1 2