【矩阵快速幂】中山纪念中学暑期游Day7——小L的数列

本文探讨了一种利用矩阵乘法和费马小定理解决特定数列求值问题的方法。通过对数列的特性分析,采用矩阵运算加速计算过程,实现了高效求解大数情况下的数列第n项值。文章详细解释了如何构建转移矩阵,并通过矩阵快速幂优化算法复杂度。

前言

看着与数学有关的题就紧张emmm......

题目

Time Limits: 1500 ms  Memory Limits: 524288 KB

Input

一行两个整数n和k。

之后1行k个正整数b1...bk。

之后1行k个正整数f1...fk。
 

Output

输出一个整数表示fn

Sample Input

样例输入1

5 4

1 2 3 4

4 3 2 1

样例输入2

100000 4

1 2 3 4

12 23 34 45

Sample Output

样例输出1

27648

样例输出2

33508797
 

【数据范围】

对于30%的数据,n≤10000.

对于另外20%的数据,bi=1,n≤1000000.

对于另外20%的数据,f[1]...f[k-1]=1.

对于另外20%的数据,k≤30.

对于100%的数据,1≤k≤200,1≤n≤40000000,1≤bi,fi≤998244352.

【样例解释】

1*2*2*3*3*3*4*4*4*4=27648

分析

贴个JZOJ的题解...:

sub1,sub2随便做,先考虑subtask3的一种做法,我们只要算那个不是一的数的指数,因此我们可以想到矩阵乘法,因为幂的乘法就相当于指数的加法,乘方相当于乘法。所以我们让向量表示当前为i,i-1---i-k中每个数中fk的指数,初始即为{0,0,0,0,...,0,1},就可以用

for(int i=1;i<=K;++i) a[i][K]=b[i],a[i][i-1]=(i!=1); 这样的矩阵转移。

然后将每个数独立来看,分别做矩乘就可以拿到subtask4的分(复杂度:k^4*logn)。但其实因为矩阵相同,所以可以将矩阵的幂预处理出来(复杂度:k^3*logn),然后就可以AC。

需要注意矩乘时指数是mod p-1(费马小定理)。

注意:n可能小于k,出题人只卡了没有特判的人10分,还送了只写这个的人10分,太良心了!!!!

好吧,好抽象...找找博客


这个博客没看懂(我太弱了):https://blog.youkuaiyun.com/enjoy_pascal/article/details/98750218

再来个博客(俩博客我就不信我看不懂):https://blog.youkuaiyun.com/qq_37656398/article/details/98785796


我醉了,真的看不懂

跑去问LZR,他说:“你想象一下,用脑子想”

这篇暂时咕咕掉... ...

暴力代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1e6,mod=998244353;
ll f[MAXN+5],b[MAXN+5];
ll n,k,ans;
ll Pow(ll a,ll x)//a^x记得取模
{
	ll ret=1,tmp=x;
	while(x--)
	{
		ret*=a;
		ret%=mod;
	} 
	return ret%mod;
}
int main()
{
	//freopen("seq.in","r",stdin);
	//freopen("seq.out","w",stdout);
	scanf("%lld%lld",&n,&k);
	bool flag=true;//fi是否全是1 
	for(int i=1;i<=k;i++)
		scanf("%lld",&b[i]);
	for(int i=1;i<=k;i++)
	{
		scanf("%lld",&f[i]);
		if(f[i]!=1)
			flag=false;
	}
	if(flag)
	{
		printf("1\n");
		return 0;
	}
	else
	{
		for(int i=k+1;i<=n;i++)
		{
			f[i]=1;
			for(int j=1;j<=k;j++)
				f[i]=(f[i]*(Pow(f[i-j],b[j])%mod))%mod;
			//printf("%d:%lld\n",i,f[i]%mod);
		} 
	}
	printf("%lld",f[n]%mod);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值