Yet Another Number Sequence(矩阵快速幂、构造矩阵典型)

Yet Another Number Sequence

求: ∑ 1 n f i ∗ i k \sum_1^n{f_i*i^k} 1nfiik
观察到k很小,对于k很小的时候可以通过二项式展开构造大小与k有关的矩阵进行递推。
f i + 1 ∗ ( i + 1 ) k = ( f i + f i − 1 ) ∗ ( i + 1 ) k = ∑ j = 0 k ( C k j ∗ i j ∗ f i + C k j ∗ i j ∗ f i − 1 ) {f_{i+1}*{(i+1)}^k}=(f_{i}+f_{i-1})*{(i+1)}^k=\sum_{j=0}^k{(C_k^j*i^j*f_{i}+C_k^j*i^j*f_{i-1})} fi+1(i+1)k=(fi+fi1)(i+1)k=j=0k(Ckjijfi+Ckjijfi1)
G i , j = f i ∗ i j , H i , j = f i − 1 ∗ i j G_{i,j}=f_{i}*i^j,H_{i,j}=f_{i-1}*i^j Gi,j=fiij,Hi,j=fi1ij
G i + 1 , k = ∑ j = 0 k ( C k j ∗ G i , j + C k j ∗ H i , j ) G_{i+1,k}=\sum_{j=0}^k{(C_k^j*G_{i,j}+C_k^j*H_{i,j})} Gi+1,k=j=0k(CkjGi,j+CkjHi,j)
那么得到了G的递推式,但是式子里有H是没有递推的,我们尝试将H纳入递推范畴
H i + 1 , k = f i ∗ ( i + 1 ) k = ∑ j = 0 k C k j ∗ f i ∗ i j = ∑ j = 0 k C k j ∗ G i , j H_{i+1,k}=f_{i}*(i+1)^k=\sum_{j=0}^k{C_k^j*f_{i}*i^j}=\sum_{j=0}^k{C_k^j*G_{i,j}} Hi+1,k=fi(i+1)k=j=0kCkjfiij=j=0kCkjGi,j
那么所有需要的递推式都出来了,这个时候就可以愉快的构造矩阵了。
观察到首先有两列数是要进行递推的分别是 G i , 0   G i , k 和 H i , 0   H i , k G_{i,0}~G_{i,k}和H_{i,0}~H_{i,k} Gi,0 Gi,kHi,0 Hi,k,分别将他们放进矩阵
那么左边
( G i + 1 , 0 G i + 1 , 1 . . . G i + 1 , k H i + 1 , 0 H i + 1 , 1 . . . H i + 1 , k ) \begin{pmatrix} G_{i+1,0} \\ G_{i+1,1} \\ . \\ . \\ . \\ G_{i+1,k} \\ H_{i+1,0} \\ H_{i+1,1} \\ . \\ . \\ . \\ H_{i+1,k} \\ \end{pmatrix} Gi+1,0Gi+1,1...Gi+1,kHi+1,0Hi+1,1...Hi+1,k
构造递推的时候的系数矩阵,就是将推出来的系数填进去就好了
( 1 1 1 1 1 1 1 2 1 1 2 1 . . . . . . . . . . C k 0 C k 1 . . C k k C k 0 C k 1 . . C k k 1 1 1 1 2 1 . . . . . . . . . . C k 0 C k 1 . . C k k ) \begin{pmatrix} 1& & & & & 1 & & & & & \\ 1& 1 & & & & 1 & 1 & & & & \\ 1& 2 & 1 & & & 1& 2 & 1& & & \\ .& . & . & . & . & . & . & .& . & .& \\ C_k^0& C_k^1 & .& . & C_k^k & C_k^0& C_k^1 & .& . & C_k^k \\ 1& & & & & & & & & & \\ 1& 1 & & & & & & & & & \\ 1& 2 & 1& & & & & & & & \\ .& .& . & .& .& .& .& . & .& .& \\ C_k^0& C_k^1 & .& . & C_k^k & & & & & & \\ & & & & & & & & & & \end{pmatrix} 111.Ck0111.Ck012.Ck112.Ck11..1.......Ckk.Ckk111.Ck0.12.Ck1.1.......Ckk.
那么
( G i + 1 , 0 G i + 1 , 1 . . . G i + 1 , k H i + 1 , 0 H i + 1 , 1 . . . H i + 1 , k ) = = ( 1 1 1 1 1 1 1 2 1 1 2 1 . . . . . . . . . . C k 0 C k 1 . . C k k C k 0 C k 1 . . C k k 1 1 1 1 2 1 . . . . . . . . . . C k 0 C k 1 . . C k k ) ∗ ( G i , 0 G i , 1 . . . G i , k H i , 0 H i , 1 . . . H i , k ) \begin{pmatrix} G_{i+1,0} \\ G_{i+1,1} \\ . \\ . \\ . \\ G_{i+1,k} \\ H_{i+1,0} \\ H_{i+1,1} \\ . \\ . \\ . \\ H_{i+1,k} \\ \end{pmatrix}==\begin{pmatrix} 1& & & & & 1 & & & & & \\ 1& 1 & & & & 1 & 1 & & & & \\ 1& 2 & 1 & & & 1& 2 & 1& & & \\ .& . & . & . & . & . & . & .& . & .& \\ C_k^0& C_k^1 & .& . & C_k^k & C_k^0& C_k^1 & .& . & C_k^k \\ 1& & & & & & & & & & \\ 1& 1 & & & & & & & & & \\ 1& 2 & 1& & & & & & & & \\ .& .& . & .& .& .& .& . & .& .& \\ C_k^0& C_k^1 & .& . & C_k^k & & & & & & \\ & & & & & & & & & & \end{pmatrix}*\begin{pmatrix} G_{i,0} \\ G_{i,1} \\ . \\ . \\ . \\ G_{i,k} \\ H_{i,0} \\ H_{i,1} \\ . \\ . \\ . \\ H_{i,k} \\ \end{pmatrix} Gi+1,0Gi+1,1...Gi+1,kHi+1,0Hi+1,1...Hi+1,k==111.Ck0111.Ck012.Ck112.Ck11..1.......Ckk.Ckk111.Ck0.12.Ck1.1.......Ckk.Gi,0Gi,1...Gi,kHi,0Hi,1...Hi,k
这样就得到了每一项的递推式,问题问我们前缀和所以我们加一维sum求前缀和
得到了式子
( G i + 1 , 0 G i + 1 , 1 . . . G i + 1 , k H i + 1 , 0 H i + 1 , 1 . . . H i + 1 , k s u m i ) = = ( 1 1 0 1 1 1 1 0 1 2 1 1 2 1 0 . . . . . . . . . . 0 C k 0 C k 1 . . C k k C k 0 C k 1 . . C k k 0 1 0 1 1 0 1 2 1 0 . . . . . . . . . . 0 C k 0 C k 1 . . C k k 0 1 1 ) ∗ ( G i , 0 G i , 1 . . . G i , k H i , 0 H i , 1 . . . H i , k s u m i − 1 ) \begin{pmatrix} G_{i+1,0} \\ G_{i+1,1} \\ . \\ . \\ . \\ G_{i+1,k} \\ H_{i+1,0} \\ H_{i+1,1} \\ . \\ . \\ . \\ H_{i+1,k} \\ sum_{i} \end{pmatrix}==\begin{pmatrix} 1& & & & & 1 & & & & & 0\\ 1& 1 & & & & 1 & 1 & & & & 0\\ 1& 2 & 1 & & & 1& 2 & 1& & & 0\\ .& . & . & . & . & . & . & .& . & .&0 \\ C_k^0& C_k^1 & .& . & C_k^k & C_k^0& C_k^1 & .& . & C_k^k &0\\ 1& & & & & & & & & & 0\\ 1& 1 & & & & & & & & & 0\\ 1& 2 & 1& & & & & & & & 0\\ .& .& . & .& .& .& .& . & .& .& 0\\ C_k^0& C_k^1 & .& . & C_k^k & & & & & & 0\\ & & & & 1& & & & & &1 \end{pmatrix}*\begin{pmatrix} G_{i,0} \\ G_{i,1} \\ . \\ . \\ . \\ G_{i,k} \\ H_{i,0} \\ H_{i,1} \\ . \\ . \\ . \\ H_{i,k} \\ sum_{i-1} \end{pmatrix} Gi+1,0Gi+1,1...Gi+1,kHi+1,0Hi+1,1...Hi+1,ksumi==111.Ck0111.Ck012.Ck112.Ck11..1.......Ckk.Ckk1111.Ck0.12.Ck1.1.......Ckk.00000000001Gi,0Gi,1...Gi,kHi,0Hi,1...Hi,ksumi1
.代表延续前面的规则,空的代表0
剩下的就是典型的矩阵快速幂,就不用多说了吧。
求答案的时候只要访问当前的前缀和 s u m n − 1 sum_{n-1} sumn1在加上当前的 G n k G_n^k Gnk就可以了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=305;
const LL INF=1e18+7;
const LL mod=1e9+7;
const double PI=acos(-1);
const double eps=1e-6;
#define pii pair<LL,int>
#define mp(x,y) make_pair(x,y)
#define sfi(a) scanf("%d",&a)
#define sfl(a) scanf("%lld",&a)
#define sff(a) scanf("%lf",&a)
#define sfs(a) scanf("%s",a)
LL C[110][110];
void init()
{
	memset(C,0,sizeof(C));
	C[0][0]=1;
	for(int i=1;i<100;++i)
	{
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;++j)
		{
			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
		}
	}
}
struct matrix
{
	LL jie[110][110];
	LL n,m;
	void init()
	{
		for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)jie[i][j]=0;
	}
	matrix operator * (const matrix &a)const
	{
		matrix b;b.n=n;b.m=a.m;
		b.init();
		for(int i=1;i<=n;++i)
		for(int j=1;j<=a.m;++j)
		{
			b.jie[i][j]=0;
			for(int k=1;k<=m;++k)
			{
				b.jie[i][j]=((jie[i][k]*a.jie[k][j])%mod+b.jie[i][j])%mod;
			}
		}
		return b;
	}
}t1,t2,t3;
matrix mpow(matrix a,LL b)
{
	matrix kk;kk.n=kk.m=a.n;
	kk=a;b--;
	while(b)
	{
		if(b&1)kk=kk*a;
		a=a*a;
		b>>=1;
	}
	return kk;
}
LL n,m;
void gao()
{
	t1.n=2*m+3;t1.m=1;
	t1.init();
	for(int i=1;i<=t1.n-1;++i)t1.jie[i][1]=1;
	t1.jie[t1.n][1]=0;
	t2.n=t2.m=2*m+3;
	t2.init();
	for(int i=1;i<=m+1;++i)
	{
		for(int j=1;j<=i;++j)
		{
			t2.jie[i][j]=t2.jie[i+1+m][j]=t2.jie[i][1+m+j]=C[i-1][j-1];
		}
	}
	t2.jie[2*m+3][1+m]=1;t2.jie[2*m+3][2*m+3]=1;
}
int main()
{
	init();
	while(sfl(n)!=EOF)
	{
		sfl(m);
		if(n==1)
		{
			printf("1\n");return 0;
		}
		gao();
		t3=mpow(t2,n-1)*t1;
		LL ans=0;
		ans=(t3.jie[m+1][1]%mod+t3.jie[m*2+3][1]%mod+mod)%mod;
		printf("%lld\n",ans);
	}
		
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值