【BZOJ 5222】[Lydsy2017省队十连测] 怪题
【BZOJ 5222】[Lydsy2017省队十连测]怪题
problem
就是要求一个奇怪的递推式子 $F_n = F_{n-1}+F_{n-2}+2*\sqrt{3+F_{n-1}F_{n-2}}$ 的第n项 $mod\ M$的值, 给定 $F_1$和 $F_2$
然后保证 $\sqrt{3+F_{n-1}F_{n-2}}$ 是个整数
$0 \leq n \leq 1e9 ,1 \leq m \leq 1e9 ,1 \leq F_0 \leq F_1 \leq 1e6$
solution
* $[80pts]$ $[0 \leq n \leq 1e5]$
这题看到一开始还以为直接递推就行了,后来发现根号这玩意儿好像根本不能取模……还好看机房里其他大佬迟迟不下键盘,我犹豫了一会儿才发现。
好进入正题,看到递推式就要想到化简转化什么什么的,这题一定是想办法把根号去掉,考场上折腾一番,尝试尝试两边平方、多带入几层等等,于是……
$$F_{n+1} = F_n+F_{n-1}+2\sqrt{3+F_nF_{n-1}}$$
处理下根号里面的内容,带入$ F_n $:
$$ \begin{aligned}
3+F_nF_{n-1} &= 3+(F_{n-1}+F{n-2}+2\sqrt{3+F_{n-1}F_{n-2}}) \times F_{n-1}n\\
&= (3+F_{n-1}F{n-2}) + (F_{n-1}+2\sqrt{3+F_{n-1}F_{n-2}}) \times F_{n-1}
\end{aligned} $$
然后考虑消掉一些项(考场上先想到的其实是下面这个东西,结果只是辅助):
$$ \begin{aligned}
F_{n+1} &= F_n+F_{n-1}+2\sqrt{3+F_nF_{n-1}}\\
(F_{n+1}-F_n-F_{n-1})^2&= 4 \times (3+F_nF_{n-1})
\end{aligned} $$
这样就可以做些替换了,继续之前的式子:
$$\begin{aligned} 3+F_nF_{n-1}&=\frac{(F_{n+1}-F_n-F_{n-1})^2}{4}+F_{n-1} \times (F_n-F_{n-2}) \end{aligned}$$
暴力拆开合并一下(这玩意儿太长了不写了~~不是我懒是因为太长影响阅读体验~~)得到:
$$ \begin{aligned}
3+F_nF_{n-1}&=\frac{(F_n^2+F_{n-1}^2+F_{n-2}^2-2F_nF_{n-2}-2F_{n-1}F_{n-2}+2F_nF_{n-1})}{4} \\
&=\frac{(F_{n}+F_{n-1}-F_{n-2})^2}{4}
\end{aligned} $$
带回最初的式子得到:
$$F_{n+1}=2F_n+2F_{n-1}-F_{n-2}$$
这就是最终的递推式了,可以直接递推加取模运算,另外注意$F_2$还要特殊计算一下,$80pts\ get$……
* $[100pts]$
一看到这种+-法的递推式就想到了矩阵乘法,折腾个矩阵乘法,搞个快速幂运算就行了
$$\begin{bmatrix}F_{n-3}&F_{n-2}&F_{n-1}\\0&0&0\\0&0&0\end{bmatrix} \times \begin{bmatrix}0&0&-1\\1&1&2\\0&0&2\end{bmatrix} = \begin{bmatrix}F_{n-2}&F_{n-1}&F_{n}\\0&0&0\\0&0&0\end{bmatrix}$$
就酱紫$100pts\ get$。
下面是我的代码,不会写矩阵乘法qwq折腾死我了……
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using std::sqrt; 6 typedef long long ll; 7 const int N = 1e3+5; 8 const int C = 1e5+5; 9 const int inf = 1e9+7; 10 #define Reset(x, y) memset(x, y, sizeof(x)) 11 #define Clean(x) Reset(x, 0) 12 #define qwq register 13 #define OvO inline 14 // const int MAXIN = 1e6; 15 // char IN[MAXIN],*SS=IN,*TT=IN; 16 // #define getchar() (SS == TT&&(TT = (SS=IN) + fread(IN,1,MAXIN,stdin), SS==TT) ? EOF:*SS++) 17 template <typename T> OvO T max(T a, T b) { return a > b ? a : b; } 18 template <typename T> OvO T min(T a, T b) { return a < b ? a : b; } 19 template <typename T> OvO void read(T &x) { 20 x = 0; T f = 1; char c = getchar(); 21 while (c<'0' || c>'9') { if (c=='-') f=-1; c = getchar(); } 22 while (c>='0' && c<='9') { x = x*10+c-'0'; c = getchar(); } 23 x *= f; 24 } 25 bool mark1; 26 int n; ll mod; 27 ll _E[3][3] = { {1, 1, 1}, {1, 1, 1}, {1, 1, 1} }; 28 ll _B[3][3] = { {0, 0, -1}, {1, 0, 2}, {0, 1, 2} }; 29 struct Matrix { 30 ll a[3][3]; 31 Matrix() { Reset(a, 0); } 32 } E, B, F; 33 Matrix mul(Matrix A, Matrix B) { 34 Matrix C; 35 for (int i = 0; i < 3; ++i) 36 for (int k = 0; k < 3; ++k) 37 for (int j = 0; j < 3; ++j) 38 C.a[i][j] = (C.a[i][j] + A.a[i][k] * B.a[k][j]) % mod; 39 return C; 40 } 41 Matrix solve(Matrix A, int p) { 42 Matrix ret = F; 43 while (p) { 44 if (p&1) ret = mul(ret, A); 45 A = mul(A, A); 46 p >>= 1; 47 } 48 return ret; 49 } 50 bool mark2; 51 int main() 52 { 53 // freopen("testin.txt", "r", stdin); 54 // freopen("stdout.txt", "w", stdout); 55 // freopen("testout.txt", "w", stdout); 56 // printf("Memory:%lfMB\n", (&mark2-&mark1)/1000.0/1000.0); 57 for (int i = 0; i < 3; ++i) { 58 for (int j = 0; j < 3; ++j) { 59 B.a[i][j] = _B[i][j]; 60 E.a[i][j] = _E[i][j]; 61 } 62 } 63 read(F.a[0][0]); read(F.a[0][1]); read(mod); read(n); 64 F.a[0][2] = ( F.a[0][0]+F.a[0][1] + 2LL*(ll)sqrt(3+F.a[0][0]*F.a[0][1]) ) % mod; 65 if (n < 3) { printf("%lld\n", F.a[0][n]); return 0; } 66 F = solve(B, n-2); 67 printf("%lld\n", F.a[0][2]); 68 return 0; 69 }