P1349题解
2325131433448687~
最近重温了矩阵乘法,A了这道题后看了看题解,没有特别详细的,我就来补一发。。。
Case 1
假设现在将问题简化为求斐波那契数列第n项Mod m的结果,且n<=10^6。。。
想必这个问题大家都会,只需要a[1]=1,a[2]=1,然后跑一边for循环,结束。。。
Case 2
现在,在Case 1的基础上,n改为n<=10^12,那么现在该如何解决呢?
此时,就需要用“矩阵快速幂”QWQ!
2.1 矩阵乘法
矩阵乘法的定义如下:
对于一个a * b的矩阵A,b * c的矩阵B,C=A * B
那么Cij=Ai1 * B1j + Ai2 * B2j+ Ai3 * B3j + …… + Aib * Bbj(C的大小为a * c)
2.2 矩阵快速幂
矩阵快速幂与快速幂相似,使用了位运算,将原本要进行的n次乘法变成了log n次,它的总时间复杂度为O(abclog n)。。。
下面是最经典的矩阵快速幂的核心代码(P3390):
struct matrix
{
long long M[MAXN][MAXN];
matrix operator *(const matrix B) const
{
matrix C;
memset(C.M, 0, sizeof(C.M));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
C.M[i][j] = (C.M[i][j]+ M[i][k]*B.M[k][j]) % MOD;
return C;
}
}A, res;
2.3 斐波那契数列取模与矩阵快速幂
不难发现,
f(n) 1 1 f(n-1)
f(n-1)= 1 0 * f(n-2)
于是,代码也就敲出来了,在这里就不展示了。。。
Case 3
那么对于本题,怎么做呢?
由于该题只是把斐波那契数列中的系数改了,所以公式应该也长得差不多。。。
只需试一试,公式就出来了:
f(n) p 1 f(n-1)
f(n-1) = q 0 * f(n-2)
于是代码写出来了:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
struct Matrix
{
ll a[2][2];
Matrix operator *(const Matrix B) const
{
Matrix C;
memset(C.a,0,sizeof(C.a));
for(ll i=0;i<2;++i)
{
for(ll j=0;j<2;++j)
{
for(ll k=0;k<2;++k)
{
C.a[i][j]+=a[i][k]*B.a[k][j];
C.a[i][j]%=m;
}
}
}
return C;
}
}res,A;
ll p,q,a1,a2;
Matrix Mul(Matrix a,ll b)
{
Matrix ans=a;
a.a[0][0]=p;
a.a[0][1]=1;
a.a[1][0]=q;
while(b)
{
if(b&1)
ans=ans*a;
a=a*a;
b=b>>1;
}
return ans;
}
int main()
{
scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&a1,&a2,&n,&m);
A.a[0][0]=a2;
A.a[0][1]=a1;
Matrix res=Mul(A,n-2);
printf("%lld",res.a[0][0]%m);
return 0;
}
2325131433448687~