原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=5221
偏题
Description
斐波那契数列是一个经典递推数列,即
F
i
b
n
=
F
i
b
n
−
1
+
F
i
n
+
n
−
2
Fib_n=Fib_{n-1}+Fin+{n-2}
Fibn=Fibn−1+Fin+n−2
在这个问题中,定义一个新数列,对于
n
≥
2
n ≥ 2
n≥2有
F
n
=
F
n
−
1
+
F
n
−
2
+
2
3
+
F
n
−
1
F
n
−
2
F_n=F_{n-1}+F_{n-2}+2\sqrt{3+F_{n-1}F_{n-2}}
Fn=Fn−1+Fn−2+23+Fn−1Fn−2
对于给出的四个整数 F 0 , F 1 , M , n F_0,F_1,M,n F0,F1,M,n,求 F n m o d M F_n\ mod\ M Fn mod M。
数据保证 3 + F n − 1 F n − 2 \sqrt{3+F_{n-1}F_{n-2}} 3+Fn−1Fn−2总是整数。
Input
一行四个整数 F 0 , F 1 , M , n F_0,F_1,M,n F0,F1,M,n。
Output
一行一个整数,表示 F n F_n Fn对 M M M取模后的值。
Sample Input
1 1 10 5
Sample Output
4
HINT
F
0
=
1
F_0=1
F0=1
F
1
=
1
F_1=1
F1=1
F
2
=
1
+
1
+
2
3
+
1
×
1
=
6
F_2=1+1+2\sqrt{3+1\times 1}=6
F2=1+1+23+1×1=6
F
3
=
6
+
1
+
2
3
+
6
×
1
=
13
F_3=6+1+2\sqrt{3+6\times 1}=13
F3=6+1+23+6×1=13
F
4
=
13
+
6
+
2
3
+
13
×
6
=
37
F_4=13+6+2\sqrt{3+13×6}=37
F4=13+6+23+13×6=37
F
5
=
37
+
13
+
2
3
+
37
×
13
=
94
F_5=37+13+2\sqrt{3+37×13}=94
F5=37+13+23+37×13=94
【数据规模】
对于 30 % 30\% 30%的数据, n ≤ 20 n≤20 n≤20。
对于 60 % 60\% 60%的数据, F 0 = F 1 = 1 F_0=F_1=1 F0=F1=1。
对于 80 % 80\% 80%的数据, n ≤ 1 0 5 n≤10^5 n≤105。
对于 100 % 100\% 100%的数据, 0 ≤ n ≤ 1 0 9 , 1 ≤ M ≤ 1 0 9 , 1 ≤ F 0 ≤ F 1 ≤ 1 0 6 0≤n≤10^9,1≤M≤10^9,1≤F_0≤F_1≤10^6 0≤n≤109,1≤M≤109,1≤F0≤F1≤106。
题解
乍一看可能需要一个二次剩余,然而我们可以先推个式子:
(
3
+
F
n
F
n
−
1
)
2
(\sqrt{3+F_nF_{n-1}})^2
(3+FnFn−1)2
=
3
+
F
n
F
n
−
1
=3+F_nF_{n-1}
=3+FnFn−1
=
3
+
(
F
n
−
1
+
F
n
−
2
+
2
3
+
F
n
−
1
F
n
−
2
)
F
n
−
1
=3+(F_{n-1}+F_{n-2}+2\sqrt{3+F_{n-1}F_{n-2}})F_{n-1}
=3+(Fn−1+Fn−2+23+Fn−1Fn−2)Fn−1
=
3
+
F
n
−
1
F
n
−
2
+
2
F
n
−
1
3
+
F
n
−
1
F
n
−
2
+
F
n
−
1
2
=3+F_{n-1}F_{n-2}+2F_{n-1}\sqrt{3+F_{n-1}F_{n-2}}+F_{n-1}^2
=3+Fn−1Fn−2+2Fn−13+Fn−1Fn−2+Fn−12
=
(
3
+
F
n
−
1
F
n
−
2
+
F
n
−
1
)
2
=(\sqrt{3+F_{n-1}F_{n-2}}+F_{n-1})^2
=(3+Fn−1Fn−2+Fn−1)2
话说为什么 C S D N \mathcal{CSDN} CSDN改版以后左对齐的语法不管用了。。。
源码如下:
\begin{align*}
&(\sqrt{3+F_nF_{n-1}})^2\\
&=3+F_nF_{n-1}\\
&=3+(F_{n-1}+F_{n-2}+2\sqrt{3+F_{n-1}F_{n-2}})F_{n-1}\\
&=3+F_{n-1}F_{n-2}+2F_{n-1}\sqrt{3+F_{n-1}F_{n-2}}+F_{n-1}^2\\
&=(\sqrt{3+F_{n-1}F_{n-2}}+F_{n-1})^2
\end{align*}
所以就有 3 + F n F n − 1 = 3 + F n − 1 F n − 2 + F n − 1 \sqrt{3+F_nF_{n-1}}=\sqrt{3+F_{n-1}F_{n-2}}+F_{n-1} 3+FnFn−1=3+Fn−1Fn−2+Fn−1,这样我们就可以将 3 + F n F n − 1 \sqrt{3+F_nF_{n-1}} 3+FnFn−1当做一项放进矩阵里递推了。
初始矩阵:
1 1 1
1 0 0
2 0 1
快速幂出来了以后再乘上一个向量 F 1 , F 0 , 3 + F 0 F 1 F_1,F_0,\sqrt{3+F_0F_1} F1,F0,3+F0F1就行了。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=105;
ll n=3,mod,a,f0,f1;
struct matrix{int sq[M][M];matrix(){memset(sq,0,sizeof(sq));}}mat,one;
matrix operator *(matrix a,matrix b)
{matrix c;for(int i=1,j,k;i<=n;++i)for(j=1;j<=n;++j)for(k=1;k<=n;++k)(c.sq[i][j]+=1ll*a.sq[i][k]*b.sq[k][j]%mod)%=mod;return c;}
matrix power(matrix x,ll p){matrix ans=one;for(;p;p>>=1,x=x*x)if(p&1)ans=ans*x;return ans;}
void in(){scanf("%lld%lld%lld%lld",&f0,&f1,&mod,&a);}
void ac()
{
one.sq[1][1]=one.sq[2][2]=one.sq[3][3]=1;
mat.sq[1][1]=mat.sq[1][2]=mat.sq[1][3]=mat.sq[2][1]=mat.sq[3][3]=1,mat.sq[3][1]=2;
mat=power(mat,a-1);
printf("%lld\n",(mat.sq[1][1]*f1%mod+mat.sq[2][1]*f0%mod+mat.sq[3][1]*(ll)sqrt(3+f0*f1)%mod)%mod);
}
int main(){in();ac();}