牛客221C公式题(2)
思路:
矩阵快速幂最难的就在推公式。
首先看f(n)=2*f(n-1)+3*f(n-2)+n;
先可以得到到如下矩阵:
2 3 1 0 f(n-1) 2*f(n-1)+3*f(n-2)+n f(n)
1 0 0 0 × f(n-2) = f(n-1) = f(n-1)
0 0 1 1 n n+1 n+1
0 0 0 1 1 1 1
然后对于g(n)=g(n-1)+f(n)+n*n;
可得:
1 2 3 1 1 0 g(n-1) g(n-1)+2*f(n-1)+3*f(n-2)+n+n^2 g(n)
0 2 3 0 1 0 f(n-1) 2*f(n-1)+3*f(n-2)+n f(n)
0 1 0 0 0 0 × f(n-2) = f(n-1) = f(n-1)
0 0 0 1 2 1 n^2 n^2+2*n+1 (n+1)^2
0 0 0 0 1 1 n n+1 n+1
0 0 0 0 0 1 1 1 1
代码:
#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;
}