A - Apple Trees
- 转自:http://zyl1213.top/blog/archives/1059
- 题意:在第0年有一个0岁的苹果树,苹果树10岁会生16个0岁的苹果树,20岁会生9个0岁的苹果树,30岁会生4个0岁的苹果树,40岁会生一个0岁的苹果树,45岁这个这个苹果树就结束了它悲惨的一生。
- 思路:一看就是递推关系,n是1e15,所以要用矩阵快速幂。
- 因为会涉及到45岁死亡问题,所以把45分成了九份:
- 0-4
- 5-9
- 10-14
- 15-19
- 20-24
- 25-29
- 30-34
- 35-39
- 40-44
- 让f[n][0]表示第i年0-4的有多少个
- 同理:
- 我们可以五年五年的推导:
- 递推关系有了,接下来就是转化成矩阵了。
- 所以,
- 那个问号表示什么呢??
- 表示的是第0,1,2,3,4年中的某一个矩阵。
- 因为我们是五年五年推的,n=6是,那么?表示的就是第一年,如果n=12,?表示的就是第2年。
- 不过很明显,第0年到第4年的矩阵是相同的,所以?就是:
- 这样矩阵关系就推完了。
f[n][0] 0 16 0 9 0 4 0 1 0
f[n][1] 1 0 0 0 0 0 0 0 0
f[n][2] 0 1 0 0 0 0 0 0 0
( f[n][3] ) = ( 0 0 1 0 0 0 0 0 0 ) 的(n/5)次方 * ( ? )
f[n][4] 0 0 0 1 0 0 0 0 0
f[n][5] 0 0 0 0 1 0 0 0 0
f[n][6] 0 0 0 0 0 1 0 0 0
f[n][7] 0 0 0 0 0 0 1 0 0
f[n][8] 0 0 0 0 0 0 0 1 0
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define md 1000000007
#define maxn 10
ll ans,b,n;
void mulp(ll x[9][9],ll y[9][9])
{
ll z[maxn][maxn];
memset(z,0,sizeof(z));
for(int k=0; k<9; k++)
for(int i=0; i<9; i++)
for(int j=0; j<9; j++)
z[i][j]=(z[i][j]+x[i][k]*y[k][j]%md)%md;
for(int i=0; i<9; i++)
for(int j=0; j<9; j++)
x[i][j]=z[i][j];
}
int main()
{
cin>>n;
if(!n)
{
cout<<1<<endl;
return 0;
}
b=n/5;
ll a[9][9]= {0,16,0,9,0,4,0,1,0,
1,0,0,0,0,0,0,0,0,
0,1,0,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,
0,0,0,0,1,0,0,0,0,
0,0,0,0,0,1,0,0,0,
0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1,0
};
ll e[9][9]= {1,0,0,0,0,0,0,0,0,
0,1,0,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,
0,0,0,0,1,0,0,0,0,
0,0,0,0,0,1,0,0,0,
0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1,0,
0,0,0,0,0,0,0,0,1
};
while(b)
{
if(b%2)
mulp(e,a);
mulp(a,a);
b/=2;
}
for(int i=0; i<9; i++)
ans=(ans+e[i][0])%md;
cout<<ans<<endl;
return 0;
}