【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 }

 

posted @ 2019-03-14 23:32  IrisEuclase  阅读(179)  评论(0编辑  收藏  举报