(矩阵快速幂)牛客221C公式题(2)

牛客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(n1)+3×f(n2)+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(n1)f(n2)n1=f(n)f(n1)n+11

然后对于 g ( n ) = g ( n − 1 ) + f ( n ) + n 2 g(n)=g(n-1)+f(n)+n^2 g(n)=g(n1)+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(n1)f(n1)f(n2)n2n1=g(n)f(n)f(n1)(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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值