【AcWing】蓝桥杯集训每日一题Day27|矩阵乘法|快速幂|205.斐波那契(C++)

ops/2024/9/25 23:22:02/
205.斐波那契
205. 斐波那契 - AcWing题库
难度:中等
时/空限制:1s / 64MB
总通过数:3220
总尝试数:4747
来源:

《算法竞赛进阶指南》
算法标签

数学知识矩阵乘法快速幂

题目内容

在斐波那契数列中,
F i b 0 = 0 , F i b 1 = 1 , F i b n = F i b n − 1 + F i b n − 2 Fib_{0}=0,Fib_{1}=1,Fib_{n}=Fib_{n-1}+Fib_{n-2} Fib0=0,Fib1=1,Fibn=Fibn1+Fibn2
(n>1)。
给定整数 n,求  F i b n Fib_{n} Fibn mod 10000。

输入格式

输入包含不超过 100 组测试用例。
每个测试用例占一行,包含一个整数 n。
当输入用例 n=−1 时,表示输入终止,且该用例无需处理。

输出格式

每个测试用例输出一个整数表示结果。
每个结果占一行。

数据范围

0≤n≤2×10^9

输入样例:
0
9
999999999
1000000000
-1
输出样例:
0
34
626
6875
题目解析

怕溢出,求第n项模10000的结果,这样就不需要写高i精度

不超过100组数据
对于每一个n,求斐波那契数列第n项模10000的结果

数据范围是0~20亿
不能用递推的方法来做,计算量是2000亿

如何优化
斐波那契数列有通项公式

a n = 1 ÷ 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] a_{n}=1\div \sqrt{ 5 } [\left( \frac{1+\sqrt{ 5 }}{2} \right)^n-\left( \frac{1-\sqrt{ 5 }}{2} \right)^n ] an=1÷5 [(21+5 )n(215 )n]
但是这个式子不适合这道题,需要做高精度,而且还要把n项精确求出来,没办法求余数

矩阵乘法快速幂的方式,容易取余数

如果可以把一道题目转换成矩阵的乘法来计算的话,就可以用快速幂来优化

先把递推的方法用一个矩阵表示出来
因为每一项都和前两项有关系,可以把 a n − 1 a_{n-1} an1 a n a_{n} an放到一个矩阵中,是一个1x2的矩阵
乘以一个2x2的矩阵,就可以得到一个新的1x2的矩阵
新的1x2的矩阵就是每一项往后递推, a n a_{n} an a n + 1 a_{n+1} an+1

如何构造矩阵,从定义来看
根据矩阵乘法规则
[ a n − 1 a n ] × [ 01 11 ] = [ a n a n + 1 ] \begin{bmatrix}{} a_{n-1} \qquad an \end{bmatrix} \times \begin{bmatrix}{} 0 1 \\ 11 \end{bmatrix}= \begin{bmatrix}{} a_{n} \qquad a_{n+1} \end{bmatrix} [an1an]×[0111]=[anan+1]
矩阵第一个元素的下标当作矩阵的下标
A n = A n − 1 × F A_{n}=A_{n-1} \times F An=An1×F
同理
A n = A n − 2 × F × F A_{n}=A_{n-2} \times F \times F An=An2×F×F
… \dots
A n = A 0 × F ⋯ × F A_{n}=A_{0} \times F\dots \times F An=A0×F×F
矩阵乘法有结合律
A n = A 0 × F n A_{n}=A_{0} \times F^n An=A0×Fn
= [ 0 , 1 ] × [ 01 11 ] n =\begin{bmatrix}{} 0,1 \end{bmatrix} \times \begin{bmatrix}{} 0 1 \\ 11 \end{bmatrix}^n =[0,1]×[0111]n
矩阵的n次方,可以类似用整数的快速幂来求
快速幂能用的前提是具有结合律

快速幂求法,时间复杂度是 O ( log ⁡ n ) O(\log n) O(logn)
矩阵乘法,复杂度再乘8

总共2万4的计算量,能过

如果用C++实现矩阵乘法的话,需要存1x2的数组和2x2的数组,还需要写两个函数,比较麻烦

如何只写一个函数

把1x2的矩阵扩充一下,下面加两个0,结果还是不变的

代码
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int MOD = 10000;void mul(int a[][2], int b[][2])
{//先定义一下结果数组int c[2][2] = {0};for (int i = 0; i < 2; i ++)for (int j = 0; j < 2; j ++)for (int k = 0; k < 2; k ++)c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;memcpy (a, c, sizeof c);//把c数组赋值到a上
}int fib(int n)
{int a[2][2] = {0, 1, 0, 0};int f[2][2] = {0, 1, 1, 1};//快速幂while (n){//如果n是奇数的话if (n & 1) mul(a, f);mul(f, f);n >>= 1;}return a[0][0];
}int main()
{int n;//逗号表达式,值等于最后一个表达式的值,这两个式子的值其实就是n!=-1while (cin >> n, n != -1)cout << fib(n) << endl;return 0;
}

http://www.ppmy.cn/ops/2860.html

相关文章

【创建型模式】工厂方法模式

一、简单工厂模式 1.1 简单工厂模式概述 简单工厂模式又叫做静态工厂方法模式。 目的&#xff1a;定义一个用于创建对象的接口。实质&#xff1a;由一个工厂类根据传入的参数&#xff0c;动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。 简单工厂模式…

ChatGPT写作术:高效撰写顶级论文

ChatGPT无限次数:点击直达 ChatGPT写作术&#xff1a;高效撰写顶级论文 在当今信息爆炸的时代&#xff0c;如何撰写出高质量的论文成为许多研究者和学生的重要课题。借助人工智能技术的不断发展&#xff0c;像ChatGPT这样的语言生成模型能够为撰写论文提供有效的帮助。本文将介…

云原生(八)、Kubernetes基础(一)

K8S 基础 # 获取登录令牌 kubectl create token admin --namespace kubernetes-dashboard1、 NameSpace Kubernetes 启动时会创建四个初始名字空间 default:Kubernetes 包含这个名字空间&#xff0c;以便于你无需创建新的名字空间即可开始使用新集群。 kube-node-lease: 该…

外包干了2个月,技术倒退2年。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;20年通过校招进入深圳某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

Sql Server 数据库:查询表结构脚本

查询脚本: SELECT CASE WHEN col.colorder 1 THEN obj.name ELSE END AS 表名, col.colorder AS 序号 , col.name AS 列名 , ISNULL(ep.[value], ) AS 列说明 , t.name AS 数据类型 , col.length AS 长度 , ISNULL(COLUMNPROPERTY(col.id, col.name, Scale), 0) AS 小数位数…

SpringBoot + minio实现分片上传、秒传、续传

什么是minio MinIO是一个基于Go实现的高性能、兼容S3协议的对象存储。它采用GNU AGPL v3开源协议&#xff0c;项目地址是https://github.com/minio/minio。 引用官网&#xff1a; MinIO是根据GNU Affero通用公共许可证v3.0发布的高性能对象存储。它与Amazon S3云存储服务兼容…

23种设计模式-Python,优缺点场景与示例代码

今天我将与大家探讨软件开发中至关重要的一些概念——设计模式。无论你是初学者还是经验丰富的开发者&#xff0c;理解这些模式都将对你的编程技能有巨大的提升。 首先什么是设计模式&#xff1f; 设计模式是解决软件设计问题中常见问题的典型解决方案。它们是被多次实践验证…

Linux-面试题

Q1&#xff1a;什么是程序&#xff0c;什么是进程&#xff0c;有什么区别&#xff1f; 程序&#xff1a; 程序是一种静态的实体&#xff0c;它是计算机中一组有序的指令集合&#xff0c;这些指令定义了完成特定任务所需的操作序列。程序通常以某种编程语言编写&#xff0c;经过…