牛客221C公式题(2)
思路:
矩阵快速幂最难的就在推公式。
首先看
f
(
n
)
=
2
×
f
(
n
−
1
)
+
3
×
f
(
n
−
2
)
+
n
f(n)=2\times f(n-1)+3\times f(n-2)+n
f(n)=2×f(n−1)+3×f(n−2)+n;
先可以得到到如下矩阵:
[
2
3
1
0
1
0
0
0
0
0
1
1
0
0
0
1
]
×
[
f
(
n
−
1
)
f
(
n
−
2
)
n
1
]
=
[
f
(
n
)
f
(
n
−
1
)
n
+
1
1
]
\begin{bmatrix}2&3&1&0\\1&0&0&0\\0&0&1&1\\0&0&0&1\end{bmatrix}\times\begin{bmatrix}f(n-1)\\f(n-2)\\n\\1\end{bmatrix}=\begin{bmatrix}f(n)\\f(n-1)\\n+1\\1\end{bmatrix}
⎣⎢⎢⎡2100300010100011⎦⎥⎥⎤×⎣⎢⎢⎡f(n−1)f(n−2)n1⎦⎥⎥⎤=⎣⎢⎢⎡f(n)f(n−1)n+11⎦⎥⎥⎤
然后对于
g
(
n
)
=
g
(
n
−
1
)
+
f
(
n
)
+
n
2
g(n)=g(n-1)+f(n)+n^2
g(n)=g(n−1)+f(n)+n2;
可得:
[
1
2
3
1
1
0
0
2
3
0
1
0
0
1
0
0
0
0
0
0
0
1
2
1
0
0
0
0
1
1
0
0
0
0
0
1
]
×
[
g
(
n
−
1
)
f
(
n
−
1
)
f
(
n
−
2
)
n
2
n
1
]
=
[
g
(
n
)
f
(
n
)
f
(
n
−
1
)
(
n
+
1
)
2
n
+
1
1
]
\begin{bmatrix}1&2&3&1&1&0\\0&2&3&0&1&0\\0&1&0&0&0&0\\0&0&0&1&2&1\\0&0&0&0&1&1\\0&0&0&0&0&1\end{bmatrix}\times\begin{bmatrix}g(n-1)\\f(n-1)\\f(n-2)\\n^2\\n\\1\end{bmatrix}=\begin{bmatrix}g(n)\\f(n)\\f(n-1)\\(n+1)^2\\n+1\\1\end{bmatrix}
⎣⎢⎢⎢⎢⎢⎢⎡100000221000330000100100110210000111⎦⎥⎥⎥⎥⎥⎥⎤×⎣⎢⎢⎢⎢⎢⎢⎡g(n−1)f(n−1)f(n−2)n2n1⎦⎥⎥⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎢⎢⎡g(n)f(n)f(n−1)(n+1)2n+11⎦⎥⎥⎥⎥⎥⎥⎤
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
#define cl(x,y) memset(x,y,sizeof(x))
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
const int N=1e6+10;
const int mod=1e9+7;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
struct mat
{
ll maze[10][10];
mat()
{
cl(maze,0);
}
};
mat mul(mat a,mat b)
{
mat c;
int i,j,k;
for(i=1;i<=6;i++)
for(j=1;j<=6;j++)
for(k=1;k<=6;k++)
c.maze[i][j]=(c.maze[i][j]+a.maze[i][k]*b.maze[k][j])%mod;
return c;
}
mat matpow(mat a,int n)
{
mat b;
int i,j;
for(i=1;i<=6;i++)
for(j=1;j<=6;j++)
b.maze[i][j]=i==j?1:0;
while(n)
{
if(n&1)
b=mul(b,a);
a=mul(a,a);
n>>=1;
}
return b;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n;
while(cin>>n && n)
{
if(n==1)
{
cout<<2<<endl;
continue;
}
mat a;
a.maze[1][1]=1;a.maze[1][2]=2;a.maze[1][3]=3;a.maze[1][4]=1;a.maze[1][5]=1;
a.maze[2][2]=2;a.maze[2][3]=3;a.maze[2][5]=1;
a.maze[3][2]=1;
a.maze[4][4]=1;a.maze[4][5]=2;a.maze[4][6]=1;
a.maze[5][5]=1;a.maze[5][6]=1;
a.maze[6][6]=1;
a=matpow(a,n-2);
mat b;
b.maze[1][1]=8;b.maze[2][1]=2;b.maze[3][1]=1;b.maze[4][1]=9;b.maze[5][1]=3;b.maze[6][1]=1;
if(n-2)
b=mul(a,b);
cout<<b.maze[1][1]<<endl;
}
return 0;
}