P8241 [COCI2013-2014#3] RIJEČI 题解
基础思路
先来看点显然的。
我们设 $A$ 的个数为 $a$,$B$ 的个数为 $b$。
经过一次变换,$A\rightarrow B,B\rightarrow BA$,
只有 $B$ 会变出 $A$,那么就有 $a\leftarrow b$。
$A,B$ 都会变出 $B$,那么就有 $b\leftarrow a+b$。
变换的次数并不多,于是可以 $O(n)$ 模拟一下。
code:
#include <cstdio>
int main()
{
int n, a = 1, b = 0, t;scanf("%d", &n);
while(n--) t = a, a = b, b += t;
return printf("%d %d", a, b), 0;
}
进阶亿点
我们发现题目中 $k$ 很小,如果 $k≥2×10^8$ 怎么办呢?
纯递推,自然想到矩阵快速幂优化。设经过 $i$ 次转移的 $a,b$ 为 $A_i,B_i$。
推一下转移矩阵:$$ \begin{bmatrix} A_{i-1}&B_{i-1} \end{bmatrix} × \begin{bmatrix} a&b\\c&d \end{bmatrix} = \begin{bmatrix} A_{i}&B_{i} \end{bmatrix} $$ 则有$$ \begin{cases} A_i=aA_{i-1}+cB_{i-1}\\ B_i=bA_{i-1}+dB_{i-1} \end{cases} $$ 我们知道$$ \begin{cases} A_i=B_{i-1}\\ B_i=A_{i-1}+B_{i-1} \end{cases} $$ 可以推得$$ \begin{bmatrix} a&b\\c&d \end{bmatrix}= \begin{bmatrix} 0&1\\1&1 \end{bmatrix} $$ 因为 $ \begin{bmatrix} A_0&B_0 \end{bmatrix}= \begin{bmatrix} 1&0 \end{bmatrix} $,所以:$$ \begin{bmatrix} 1&0 \end{bmatrix} × \begin{bmatrix} 0&1\\1&1 \end{bmatrix}^n = \begin{bmatrix} A_{n}&B_{n} \end{bmatrix} $$ 矩阵快速幂即可。
#include <cstdio>
#include <cstring>
#define F(i) for(int i = 0;i < 2;++i)
struct S{int a[2][2];S() {memset(a, 0, sizeof a);}S operator*(S b);}b, s;
S S::operator*(S b) {S c;F(k) F(i) F(j) c.a[i][j] += a[i][k] * b.a[k][j];return c;}
signed main()
{
int n;scanf("%d", &n);
s.a[0][0] = b.a[0][1] = b.a[1][0] = b.a[1][1] = 1;
for(;n;n >>= 1) {if(n & 1) s = s * b;b = b * b;}
return printf("%d %d", s.a[0][0], s.a[0][1]), 0;
}