P8241 [COCI2013-2014#3] RIJEČI 题解

基础思路

先来看点显然的。

我们设 A 的个数为 aB 的个数为 b

经过一次变换,AB,BBA

只有 B 会变出 A,那么就有 ab

A,B 都会变出 B,那么就有 ba+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 很小,如果 k2×108 怎么办呢?

纯递推,自然想到矩阵快速幂优化。设经过 i 次转移的 a,bAi,Bi

推一下转移矩阵:[Ai1Bi1]×[abcd]=[AiBi] 则有{Ai=aAi1+cBi1Bi=bAi1+dBi1 我们知道{Ai=Bi1Bi=Ai1+Bi1 可以推得[abcd]=[0111] 因为 [A0B0]=[10],所以:[10]×[0111]n=[AnBn] 矩阵快速幂即可。

#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;
}
posted @   Jijidawang  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示