CF392C Yet Another Number Sequence 题解

题目传送门

题意:

斐波那契数列 F1=1,F2=2,Fi=Fi1+Fi2(i>2)。对于数列 A,Ai(k)=Fi×ik(i>1).求 A1(k)+A2(k)+...An(k),答案对 109+7 取模。

解题思路

发现 n<=1017,考虑使用矩阵加速。因为矩阵中向量只能求和不能相乘,所以我们只能把 Fi×ik 看成一个整体。接着考虑转移,首先 Fi=Fi1+Fi2,然后对于 ik=(i1+1)k。对其进行二项式展开得 (i1+1)k=r=0kCkr×(i1)k.所以把 拆开得到矩阵:

[(i1)0×Fi2(i1)1×Fi2(i1)k×Fi2(i1)0×Fi1(i1)1×Fi1(i1)k×Fi1]×C=[i0×Fi1i1×Fi1ik×Fi1i0×Fii1×Fiik×Fi]

接着思考如何构建操作矩阵 C。显然 i0×Fi1=(i1)0×Fi1,i1×Fi1=(i1)0×Fi1+(i1)1×Fi1,i2×Fi1=(i1)0×Fi1+2×(i1)1×Fi1+(i1)2×Fi1.其实就是一个杨辉三角。 i0×Fi=(i1)0×(Fi2+Fi1),所以就是两个杨辉三角,这样就得到了操作矩阵 C

[000010000000110000001210100010001100110012101210]

AC代码

(码风不好不喜勿喷)

#include<iostream>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
const int mod=1e9+7;
struct Matrix{//矩阵结构体 
	vector<vector<int> > mp;
	Matrix(int n,int val=0):mp(n,vector<int>(n,0)){
		for(int i=0;i<n;i++) mp[i][i]=val;
	}
	Matrix(const vector<vector<int> >& _m):mp(move(_m)){}
	Matrix operator*(const Matrix& _m)const{
		int n=mp[0].size();
		Matrix res(n);
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				for(int k=0;k<n;k++)
					res.mp[i][j]=(res.mp[i][j]+mp[i][k]*_m.mp[k][j])%mod;
		return res;
	}
	Matrix operator^(int l){
		Matrix res(mp.size(),1),tmp=*this;
		while(l){
			if(l&1) res=res*tmp;
			tmp=tmp*tmp;
			l>>=1;
		}
		return res;
	}
};
int n,k,ans;
signed main(){
	scanf("%lld%lld",&n,&k);
	if(n==1){
		printf("1");
		return 0;
	}
	if(n==2){
		printf("%lld",1+2*(1<<k));
		return 0;
	}//特判小于等于二的情况 
	Matrix C((k<<1)+3);
	C.mp[0][k+1]=1;
	for(int i=1;i<k+1;i++){
		for(int j=k+1;j<(k<<1)+2;j++){
			if(j==k+1) C.mp[i][j]=1;
			else C.mp[i][j]=(C.mp[i-1][j-1]+C.mp[i-1][j])%mod;
		}
	}
	C.mp[k+1][0]=C.mp[k+1][k+1]=1;
	for(int i=k+2;i<(k<<1)+2;i++){
		for(int j=0;j<k+1;j++){
			if(j==0) C.mp[i][j]=C.mp[i][j+k+1]=1;
			else C.mp[i][j]=C.mp[i][j+k+1]=(C.mp[i-1][j-1]+C.mp[i-1][j])%mod;
		}
	}
	for(int i=0;i<(k<<1)+2;i++) C.mp[(k<<1)+2][i]=C.mp[(k<<1)+1][i];
	C.mp[(k<<1)+2][(k<<1)+2]=1;//创建操作矩阵C 
	C=C^(n-1);//矩阵快速幂 
	for(int i=0;i<(k<<1)+3;i++) ans=(ans+C.mp[(k<<1)+2][i])%mod;//统计答案 
	printf("%lld",ans%mod);
	return 0;
}
posted @   Fhr123456  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示