文章目录

  • 快速幂
  • 矩阵快速幂
  • 慢速乘
  • 例题
    • HDU-2817
    • HDU-3117
    • XUJC-1395

快速幂


首先幂运算 a n a^n an就是 n n n个 a a a相乘,我们可以直接调用库函数 p o w ( a , n ) pow(a,n) pow(a,n)来计算,时间复杂度是 O ( n ) O(n) O(n)。不过直接调用往往会超时,还会数据溢出,而快速幂的复杂度是 O ( l o g ( n ) ) O(log(n)) O(log(n)),同时对中间结果进行取模,不会溢出。
快速幂的原理用了位运算。比如把 a 11 a^{11} a11分解成 a 8 、 a 2 、 a 1 a^8、a^2、a^1 a8、a2、a1的乘积,那么如何求 a 8 、 a 2 、 a 1 a^8、a^2、a^1 a8、a2、a1?其实不需要分别计算,因为 a 1 × a 1 = a 2 , a 2 × a 2 = a 4 , a 4 × a 4 = a 8 a_1×a_1=a_2,a_2×a_2=a_4,a_4×a_4=a_8 a1​×a1​=a2​,a2​×a2​=a4​,a4​×a4​=a8​都是2的倍数,逐级递推就可以了。
那么怎么分解成11=8+2+1?其实用二进制就一目了然了。1110=10112=23+21+20=8+2+1,按二进制处理,为0的跳过即可。

int fastpow(int a, int n) {int res = 1;while (n) {if (n & 1)  //末位为1res = (res * a) % mod;a = (a * a) % mod;n >>= 1;    //n右移一位}return res;
}

矩阵快速幂


矩阵幂运算是给定一个m阶矩阵A,求它的n次幂 A n A^n An,复杂度是 O ( m 3 n ) O(m^3n) O(m3n)。矩阵快速幂原理同快速幂一样,只是矩阵乘法无法优化,其复杂度是 O ( m 3 l o g ( n ) ) O(m^3log(n)) O(m3log(n))。

struct matrix {int a[maxn][maxn];  //矩阵amatrix() {  //构造时初始化memset(a, 0, sizeof(a));}
};
matrix multi(matrix x, matrix y) {  //矩阵乘法matrix res;for (int i = 0; i < maxn; i++)for (int j = 0; j < maxn; j++)for (int k = 0; k < maxn; k++)res.a[i][j] = (res.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;return res;
}
matrix fastm(matrix a, int n) { //矩阵快速幂matrix res;for (int i = 0; i < maxn; i++)res.a[i][i] = 1;    //初始化为单位矩阵while (n) {if (n & 1)res = multi(res, a);a = multi(a, a);n >>= 1;}return res;
}

慢速乘


慢速乘,顾名思义,之所以慢是因为把乘法拆成了若干次加法运算,但是我们可以在每次加法时对中间结果进行取模,所以可以防止大数相乘溢出,其原理同快速幂,不再赘述。

ll mul(ll a, ll b) {ll res = 0;while (b) {if (b & 1)res = (res + a) % mod;a <<= 1;a %= mod;b >>= 1;}return res;
}

例题


HDU-2817

HDU-2817 A sequence of numbers

Problem Description
Xinlv wrote some sequences on the paper a long time ago, they might be arithmetic or geometric sequences. The numbers are not very clear now, and only the first three numbers of each sequence are recognizable. Xinlv wants to know some numbers in these sequences, and he needs your help.
Input
The first line contains an integer N, indicting that there are N sequences. Each of the following N lines contain four integers. The first three indicating the first three numbers of the sequence, and the last one is K, indicating that we want to know the K-th numbers of the sequence.
You can assume 0 < K <= 10^9, and the other three numbers are in the range [0, 2^63). All the numbers of the sequences are integers. And the sequences are non-decreasing.
Output
Output one line for each test case, that is, the K-th number module (%) 200907.
Sample Input
2
1 2 3 5
1 2 4 5
Sample Output
5
16

分析
给出序列前3项,要求输出第n项,判断一下等差还是等比,等比的话套快速幂。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 200907
ll fastpow(ll a, ll n) {ll res = 1;while (n) {if (n & 1)res = (res * a) % mod;a = (a * a) % mod;n >>= 1;}return res;
}
int main() {ll n, a, b, c, k;cin >> n;while (n--) {cin >> a >> b >> c >> k;if (c - b == b - a)cout << ((k - 3) * (b - a) + c) % mod << "\n";elsecout << (fastpow(c / b, k - 1) * a) % mod << "\n";}return 0;
}

HDU-3117

HDU-3117 Fibonacci Numbers

Problem Description
The Fibonacci sequence is the sequence of numbers such that every element is equal to the sum of the two previous elements, except for the first two elements f0 and f1 which are respectively zero and one.
What is the numerical value of the nth Fibonacci number?
Input
For each test case, a line will contain an integer i between 0 and 108 inclusively, for which you must compute the ith Fibonacci number fi. Fibonacci numbers get large pretty quickly, so whenever the answer has more than 8 digits, output only the first and last 4 digits of the answer, separating the two parts with an ellipsis (“…”).
There is no special way to denote the end of the of the input, simply stop when the standard input terminates (after the EOF).
Sample Input
0
1
2
3
4
5
35
36
37
38
39
40
64
65
Sample Output
0
1
1
2
3
5
9227465
14930352
24157817
39088169
63245986
1023…4155
1061…7723
1716…7565

分析
输出第n位斐波那契数列的前四位和后四位,不足8位则直接输出。
首先通项公式 a n = 1 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] a_n=\frac{1}{\sqrt5}[(\frac{1+\sqrt5}{2})^n-(\frac{1-\sqrt5}{2})^n ] an​=5 ​1​[(21+5 ​​)n−(21−5 ​​)n],前四位用科学计数法求,并且第40个以前不足8位的直接暴力。
关键是后四位!由递推公式 F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n)=F(n-1)+F(n-2) F(n)=F(n−1)+F(n−2)构造矩阵,转换成求这个矩阵的n次幂,再套用矩阵快速幂即可。
[ F ( n + 1 ) F ( n ) F ( n ) F ( n − 1 ) ] = [ 1 1 1 0 ] n \begin{bmatrix} F(n+1) & F(n) \\F(n) & F(n-1)\end{bmatrix}=\begin{bmatrix}1&1\\1 &0\end{bmatrix}^n [F(n+1)F(n)​F(n)F(n−1)​]=[11​10​]n

#include<bits/stdc++.h>
using namespace std;
#define mod 10000  //取后四位
const int maxn = 2;  //2阶矩阵
int f[40], n;
struct matrix {int a[maxn][maxn];  matrix() { memset(a, 0, sizeof(a));}
};
matrix multi(matrix x, matrix y) { matrix res;for (int i = 0; i < maxn; i++)for (int j = 0; j < maxn; j++)for (int k = 0; k < maxn; k++)res.a[i][j] = (res.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;return res;
}
matrix fastm(matrix a, int n) {matrix res;for (int i = 0; i < maxn; i++)res.a[i][i] = 1;   while (n) {if (n & 1)res = multi(res, a);a = multi(a, a);n >>= 1;}return res;
}
void init() {f[0] = 0;f[1] = 1;for (int i = 2; i < 40; i++)f[i] = f[i - 1] + f[i - 2];
}
int main() {init();while (~scanf("%d",&n)) {if (n < 40) {printf("%d\n", f[n]);continue;}double pre = log10(1.0 / sqrt(5.0)) + (double)n * log10((1.0 + sqrt(5.0)) / 2.0);pre = pre - (int)pre;printf("%d", (int)(1000.0 * pow(10.0, pre)));printf("...");matrix last;last.a[0][0] = last.a[0][1] = last.a[1][0] = 1;last = fastm(last, n);printf("%0.4d\n", last.a[0][1]);//注意巨坑:前导0}return 0;
}

XUJC-1395

XUJC-1395数列乘积

描述
给定 n 个数字,求解 ( ∏ i = 1 n a i ) \left (\prod_{i = 1}^{n}{a}_{i}\right ) (∏i=1n​ai​)%mod
输入
第一行是一个正整数 T 代表测试案例的数量。
第二行输入两个数字 n 和 mod,代表数字个数和模数。
然后输入 n 个数字。
针对40%的样例, ( ∏ i = 1 n a i ) < = 1 e 9 , m o d < = 1 e 9 , 1 < = a i < = 1 e 9 \left (\prod_{i = 1}^{n}{a}_{i}\right )<={1e9},mod<=1e9 ,1<=a_i<=1e9 (∏i=1n​ai​)<=1e9,mod<=1e9,1<=ai​<=1e9
针对60%的样例, ( ∏ i = 1 n a i ) < = 1 e 18 , m o d < = 1 e 18 , 1 < = a i < = 1 e 18 \left (\prod_{i = 1}^{n}{a}_{i}\right )<={1e18} ,{mod}<=1e18 ,1<=a_i<=1e18 (∏i=1n​ai​)<=1e18,mod<=1e18,1<=ai​<=1e18
针对100%的样例, ( ∏ i = 1 n a i ) < = 1 e 100000 , m o d < = 1 e 18 , 1 < = a i < = 1 e 100000 \left (\prod_{i = 1}^{n}{a}_{i}\right )<={1e100000} ,{mod}<=1e18 ,1<=a_i<=1e100000 (∏i=1n​ai​)<=1e100000,mod<=1e18,1<=ai​<=1e100000
每组样例的 n 的总和不会超过 3e5。
输出
针对每组样例,输出 ( ∏ i = 1 n a i ) \left (\prod_{i = 1}^{n}{a}_{i}\right ) (∏i=1n​ai​)%mod的结果,然后换行。
样例输入
2
3 100
2 5 7
3 10
2 5 7
样例输出
70
0
HINT
2 × 5 × 7 = 70

分析
首先用字符串数组读入数,然后取模,使其范围缩小至1e18,然后套用慢速乘即可,

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int maxn = 100005;
int t, n;
ll mod, ans, y;
char x[maxn];
ll getmod(char* x) {int lx = strlen(x);ll yu = 0;for (int i = 0; i < lx; i++) {yu = (yu * 10) + x[i] - '0';if (yu >= mod)yu %= mod;}return yu;
}
ll mul(ll a, ll b) {ll res = 0;while (b) {if (b & 1)res = (res + a) % mod;a <<= 1;a %= mod;b >>= 1;}return res;
}
int main() {scanf("%d", &t);while (t--) {scanf("%d%lld", &n, &mod);scanf("%s", x);ans = getmod(x);bool tag = false;for (int i = 1; i < n; i++) {scanf("%s", x);if (tag)continue;y = getmod(x);ans = mul(ans, y);if (ans == 0)tag = true;}printf("%lld\n", ans);}return 0;
}

原创不易,请勿转载(本不富裕的访问量雪上加霜 )
博主首页:https://blog.csdn.net/qq_45034708
如果文章对你有帮助,记得一键三连❤

数论-快速幂、矩阵快速幂、慢速乘相关推荐

  1. 快速幂 + 矩阵快速幂

    快速幂 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #define LL lo ...

  2. hdu 4549 M斐波那契数列(费马小定理 + 二分快速幂 + 矩阵快速幂)

    M斐波那契数列                                                                           Time Limit: 3000/1 ...

  3. 40行代码AC_HDU 1575 TrA 矩阵快速幂(附快速幂+矩阵快速幂的讲解)

    一道经典的矩阵快速幂模板题. 传送门1-->快速幂基本思想 传送门2-->矩阵快速幂讲解(教主传授) 心路历程 1.开始看成求主对角线元素和的n次幂了,用快速幂解得.结果压根不对,又仔细看 ...

  4. 快速幂+矩阵快速幂(总结+例题)

    1.快速幂 以求a的b次方来介绍: 首先把b转换成二进制数 该二进制数第i位的权为  2^i - 1 . 比如 : 11的二进制是1011 11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1 ...

  5. 快速幂+矩阵快速幂模板

    快速..运算 快速幂 运用位运算 代码 分析 矩阵快速幂 题目 分析 代码 拓一..: 快速幂 运用位运算 强大的位运算把我搞得蒙蒙的 理解了之后我表示很喜欢!!! 代码 int power(int ...

  6. 快速幂、矩阵快速幂、快速乘法

    快速幂 快速幂是我们经常用到的一种算法,快速幂顾名思义就是快速的幂运算.我们在很多题目中都会遇到幂运算,但是在指数很大的时候,我们如果用for或者是pow就会超时,这时候就用到了快速幂. 快速幂的原理 ...

  7. 矩阵问题入门(矩阵乘法and矩阵快速幂)acm寒假集训日记22/1/15

    今天凌晨3点才睡,没想到通过看小说抑制玩游戏,反而看小说的时间更长. u1s1:那小说太刺激了,晚上看很有感觉,风吹草动我就会猛地看过去(类似茄子说柜子动了,哈哈),真TM(语气词)练胆量!!!..Q ...

  8. 二分幂,快速幂,矩阵快速幂,快速乘

    前言 二分幂,快速幂,矩阵快速幂在算大指数次方时是很高效的. 求 a^n 的值是多少?n是1到10^18次方的一个整数. 求一个数的n次方,朴素的算法就是直接for循环,一遍一遍的乘,a*a*a*a* ...

  9. 快速幂和矩阵快速幂详解+模板

    1.快速幂 一般的,我们都知道求只需要连续乘3次2就能得到,那么等于多少呢?其实这个一很简单,不就是13个2相乘吗,连续乘13次2就行了.那么,呢? 是不是要连续乘100次.1000次,我们将这类问题 ...

最新文章

  1. Linux.NET学习手记(2)
  2. 自译Solr in action中文版
  3. BUUCTF--pwn picoctf_2018_buffer overflow 0
  4. 【深搜】骑士游历(ssl 1277)
  5. Dubbo-admin的安装
  6. 编译 Linux2.6 内核总结【ZT】
  7. 通过SessionID和用户名来保证同一个用户不能同时登录
  8. Android中的Handler的机制与用法详解
  9. 模糊评价模型-以2018美赛为例
  10. python人工智能-图像识别
  11. IOS-性能优化/内存优化常用方法小总结
  12. 优质的凉亭 亭子 亭台ps后期素材素材推荐,不容错过
  13. 爬虫需谨慎,你不知道的爬虫与反爬虫套路!
  14. 耶鲁大学心态(估计是杜撰的) 送给正在奋斗的人
  15. FLASH,宣传画册,翻书效果
  16. 连通图 P3387 缩点 模板
  17. android qq 设置界面大小设置,怎么设置手机腾讯QQ的字体大小
  18. o.s.b.d.LoggingFailureAnalysisReporter报错
  19. 查找SAPParameterID_SAP刘梦_新浪博客
  20. oracle小机系统,【案例分享】Oracle系统参数过小导致数据库宕机

热门文章

  1. 拉勾教育管理系统(后端)
  2. PHPMyWind支持ppt上传
  3. MAC下解压(.xip)文件
  4. 【Linux】电子词典
  5. 最后一个问题得到解决
  6. LAMP--MySQL数据库
  7. ndk编译 错误:dlopen failed:cannot locate symbol 一个符号 referenced by 你的库.so/.a lang.UnsatisfiedLinkErr
  8. 6.22 Java练习(根据输入的值计算BMI的值,根据标准判断BMI的值并给出相应健康提示。)
  9. dpdk中文-DPDK学习路线图
  10. vsCode安装使用教程和插件安装