题意
定 义 f ( n ) = f ( n − 1 ) ⋅ f ( n − 2 ) ⋅ f ( n − 3 ) ⋅ c 2 n − 6 ( n ≥ 4 ) 。 给 定 n , f ( 1 ) , f ( 2 ) , f ( 3 ) 和 c , 求 f ( n ) 对 1 0 9 + 7 取 模 的 结 果 。 定义f(n)=f(n-1)⋅f(n-2)⋅f(n-3)⋅c^{2n-6} (n≥4)。 给定n,f(1),f(2),f(3)和c,求f(n)对10^9+7取模的结果。 定义f(n)=f(n−1)⋅f(n−2)⋅f(n−3)⋅c2n−6(n≥4)。给定n,f(1),f(2),f(3)和c,求f(n)对109+7取模的结果。
题解
首先看到
c
2
n
−
6
c^{2n-6}
c2n−6,它非常不优美,因此将它转化一下,
变成
c
n
×
f
(
n
)
=
c
n
−
1
×
f
(
n
−
1
)
×
c
n
−
2
×
f
(
n
−
2
)
×
c
n
−
3
×
f
(
n
−
3
)
c^n\times f(n)=c^{n-1}\times f(n-1)\times c^{n-2}\times f(n-2)\times c^{n-3}\times f(n-3)
cn×f(n)=cn−1×f(n−1)×cn−2×f(n−2)×cn−3×f(n−3).
哎呦,经过这一手高妙的变换,我们可以无视
c
c
c这个东西了.
接下去的问题是矩阵快速幂只能解决加和型递推,如何改造成乘积型递推呢?
把
f
(
n
)
f(n)
f(n)用
f
(
1
)
f(1)
f(1),
f
(
2
)
f(2)
f(2),
f
(
3
)
f(3)
f(3)代替!
1 1 1
1 0 0
0 1 0
0 0 1
此矩阵为转移矩阵.
矩阵快速幂可以处理出第一行的三个数字
k
1
k1
k1,
k
2
k2
k2,
k
3
k3
k3分别代表
f
(
n
)
f(n)
f(n)是由多少个
f
(
1
)
f(1)
f(1),
f
(
2
)
f(2)
f(2),
f
(
3
)
f(3)
f(3)相乘得到的.
接下来又有一个问题.矩阵乘法必定要取模,可是我们现在递推的内容是指数,直接取模是不相等的,又该如何解决呢?
styx大佬:欧拉降幂!
由于本题模数为质数,直接用欧拉降幂公式中的第一条即可解决.
此时
ϕ
(
x
)
=
x
−
1
\phi(x)=x-1
ϕ(x)=x−1.
所以矩阵快速幂中的模数为
1
0
9
+
6
10^9+6
109+6,千万不要打错,不然你怎么调都调不出来.
乘出来之后要除以
c
n
c^n
cn,这个大家都知道,上逆元就可以了.
好了,解决,代码如下.
结果因为好久没打代码了绿得不行,连快速幂都写错了,调了好久,呜呜呜.
#include<bits/stdc++.h> //Ithea Myse Valgulious
/*省略快读快写*/
using namespace std;
const int mod=1e9+7,l=4;
struct juzhen{
ll a[105][105];
void clearit() {
memset(a,0,sizeof a);
for (int i=1;i<=l;++i) a[i][i]=1;
}
juzhen operator *(const juzhen &r) {
int i,j,k; juzhen ans;
memset(ans.a,0,sizeof ans.a);
for (i=1;i<=l;++i)
for (j=1;j<=l;++j)
for (k=1;k<=l;++k)
ans.a[i][j]=(ans.a[i][j]+a[i][k]*r.a[k][j]%(mod-1))%(mod-1);
return ans;
}
juzhen operator ^(ll b) {
juzhen ans;
ans.clearit();
for (;b;b>>=1,*this=*this**this) if (b&1) ans=ans**this;
return ans;
}
void print() {
int i,j;
for (i=1;i<=l;++i,pl)
for (j=1;j<=l;++j) printf("%d ",a[i][j]);
}
};
ll kasumi(ll a,ll b=mod-2) { //快速幂没有第二个自变量即为求逆元
ll ans=1;
for (;b;b>>=1,a=a*a%mod) if (b&1) ans=ans*a%mod;
return ans;
}
juzhen q;
int main() {
ll n,f1,f2,f3,c;
read(n),read(f1),read(f2),read(f3),read(c);
f1=f1*c%mod,f2=f2*kasumi(c,2)%mod,f3=f3*kasumi(c,3)%mod;
q.a[1][1]=q.a[1][2]=q.a[1][3]=1;
q.a[2][1]=q.a[3][2]=q.a[4][3]=1;
q=q^(n-3);
ll lxy=kasumi(f1,q.a[1][3])*kasumi(f2,q.a[1][2])%mod*kasumi(f3,q.a[1][1])%mod;
printf("%lld\n",lxy*kasumi(kasumi(c),n)%mod);
}
Thank you for reading.