Codeforces Round #566 (Div. 2)-E. Product Oriented Recurrence

地址:https://codeforces.com/contest/1182/problem/E

思路:矩阵快速幂

fn=c^(2n−6)⋅f(n−1)⋅f(n−2)⋅f(n−3)=c^sc * f1^s1 * f2^s2 * f3^s3

因此分别算出s1,s2,s3和sc的值即可算出 fn

而由f4开始按照fn=c^(2n−6)⋅f(n−1)⋅f(n−2)⋅f(n−3)=c^sc * f1^s1 * f2^s2 * f3^s3推

       f1   f2    f3    c

f4    1     1     1    2

f5    1     2     2    6

f6    2     3     4    14

f7    4     6     7    30

f8    7    11    13   60

到f7时 对f1(7):f7=f6+f5+f4   f2(7)=f1(7)+f1(6)    f3(7)=f1(8)    而 fc(7)=fc(6)+fc(5)+fc(4)+2*7-6

因此

f1(n)=f1(n-1)+f1(n-2)+f1(n-3)

f2(n)=f1(n)+f1(n-1)

f3(n)=f1(n+1)

fc(n)=fc(n-1)+fc(n-2)+fc(n-3)+2*n-6

那么就可以用矩阵快速幂来求出f1(n),fc(n),从而得到 s1,s2,s3,sc

注意的是,在求f1(n),fc(n)时由于 其是 f1,c的幂系数,在取模时要用费马小定理(a^(p-1)=1 mod(p))来取模 即 MOD=1e9+6

在求f1^s1时 MOD=1e9+7

Code:

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;

LL MOD=1e9+6;
const int MAX_S=5;
struct Matrix{
	LL a[MAX_S][MAX_S];
	Matrix (){
		memset(a,0,sizeof(a));
	}
	Matrix operator*(const Matrix &A){
		Matrix B=Matrix();
		for(int k=0;k<MAX_S;++k)
			for(int i=0;i<MAX_S;++i)
				for(int j=0;j<MAX_S;++j)
					B.a[i][j]=(B.a[i][j]+a[i][k]*A.a[k][j])%MOD;
		return B;
	}
};
LL n,c,f[5];

Matrix mypowMa(Matrix A,LL n){
	Matrix res=Matrix();
	if(n<=0)	return res;
	for(int i=0;i<MAX_S;++i)
		res.a[i][i]=1;
	while(n){
		if(n&1)	res=res*A;
		A=A*A;
		n>>=1;
	}
	return res;
}

LL mypowLL(LL a,LL n){
	LL res=1;
	while(n){
		if(n&1)	res=res*a%MOD;
		a=a*a%MOD;
		n>>=1;
	}
	return res;
}
int main()
{
	Matrix A=Matrix(),res;
	A.a[0][0]=A.a[0][1]=A.a[0][2]=1;
	A.a[1][0]=A.a[2][1]=1;
	cin>>n>>f[1]>>f[2]>>f[3]>>c;
	LL s1,s2,s3,sc,ni=n-3,d[5]={0,1,1,2,4};
	if(ni<=3){
		s1=d[ni];	s2=s1+d[ni-1];	s3=d[ni+1];
	}else{
		res=mypowMa(A,ni-3);
		s1=(res.a[0][0]*d[3]%MOD+res.a[0][1]*d[2]%MOD+res.a[0][2]*d[1]%MOD)%MOD;
		res=mypowMa(A,ni-4);
		s2=(s1+(res.a[0][0]*d[3]%MOD+res.a[0][1]*d[2]%MOD+res.a[0][2]*d[1]%MOD)%MOD)%MOD;
		res=mypowMa(A,ni-2);
		s3=(res.a[0][0]*d[3]%MOD+res.a[0][1]*d[2]%MOD+res.a[0][2]*d[1]%MOD)%MOD;
	}
	A.a[0][3]=A.a[0][4]=A.a[3][3]=A.a[3][4]=A.a[4][4]=1;
	res=mypowMa(A,n-3);
	sc=res.a[0][4]*2%MOD;
	MOD+=1;
	LL ans=mypowLL(c,sc);
	ans=ans*mypowLL(f[1],s1)%MOD;
	ans=ans*mypowLL(f[2],s2)%MOD;
	ans=ans*mypowLL(f[3],s3)%MOD;
	cout<<ans<<endl;
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值