关于什么是快速幂:快速幂代码
现在回想下问题斐波那契数列:。在时, 。求。
朴素动态规划解法:
1 | int fib(int n) { |
现在考虑是由和线性变换得出。则有:
设矩阵为。
则有
因为矩阵乘法满足结合律,所以我们可以直接用矩阵的幂来得到的值。而求矩阵的时间复杂度为。
C++代码如下
1 | const int maxn = 105; |
完整代码如下:
1 |
|
这里暂且不考虑溢出问题。当足够大的时候,可以看到快速幂需要的时钟周期明显缩短。
关于什么是快速幂:快速幂代码
现在回想下问题斐波那契数列:f(1)=1,f(2)=1。在n>2时, f(n)=f(n−1)+f(n−2)。求f(n)。
朴素动态规划解法:
1 | int fib(int n) { |
现在考虑Fn是由Fn−1和Fn−2线性变换得出。则有:
[Fn Fn−1]=[Fn−1 Fn−2]×[1110]
设矩阵[1110]为P。
则有
[Fn+1 Fn]=[Fn Fn−1]×[1110]=[Fn−1 Fn−2]×[1110]2=[Fn−1 Fn−2]×P2
因为矩阵乘法满足结合律,所以我们可以直接用矩阵P的幂来得到Fn的值。而求矩阵Pn的时间复杂度为O(log(n))。
C++代码如下
1 | const int maxn = 105; |
完整代码如下:
1 | #include <iostream> |
这里暂且不考虑溢出问题。当n足够大的时候,可以看到快速幂需要的时钟周期明显缩短。
基础问题:求数字 a 的 n 次方。
最基本的想法,就是一次一次相乘,时间复杂度为 O(n)。
代码如下:
1 | using ll = long long; |
稍微思考一下便可得知,计算一个数的n次方并不需要相乘 n 次。我们如果知道 a 的 n/2 次方,便可以用两个 an/2 相乘,获得 an。顺着这个思想往下想,可以考虑把 n 拆成二进制的形式,这样只要把对应的二进制位数得到的幂相乘起来就可以得出答案了。举例:当 n 为 7 时,我们要 67。7 按照二进制可以拆成 00000111。那我们只要知道 61,62 和 64,再把他们相乘就可以了。
代码如下:
1 | ll qpow(ll a, ll n) |
一为递归的方式,二为迭代的方式。考虑到调用栈切换,方式二会快一些。这种把幂拆成二进制的方法,就被称为快速幂。
完整代码如下:
1 | #include <iostream> |
可以看到后面两种cpu周期普遍低于前一种。
priority_queue是C++的一种STL容器,实现为堆。在leetcode刷题中非常常用。有些时候我们需要塞入自定义的数据结构。这样就需要对其的排序方式做一个重新定义。
假设有以下数据结构
1 | struct node { |
对比方式为只看x的大小。把x的值大的放在堆顶。
则对比函数cmp写法如下:
用这种方式,需要显示的定义优先队列的容器类型(vector)以及比较函数(cmp)。
1 | #include<iostream> |
结果:
1 | @└────> # ./pq |
重载需要比较类型的<符号,之后在类型直接写类型名称即可。
1 | #include<iostream> |
结果:
1 | @└────> # ./pq |
使用lambda表达式需要在pq对象构造的时候,将lambda表达式作为参数传入其中。即pq(cmp)。
1 | #include<iostream> |
结果:
1 | @└────> # ./pq |
这种方式和lambda表达式的方式很类似。
1 | #include<iostream> |
结果:
1 | @└────> # ./pq |
reference:
https://blog.csdn.net/Strengthennn/article/details/119078911
客户端:
1 | #define _GNU_SOURCE 1 |
服务器:
1 | #define _GNU_SOURCE 1 |
演示结果:
服务器:
客户端1:
客户端2:
reference:
linux高性能服务器编程——游双
假设有如下场景:函数 A 调用了函数 B。寄存器 %rbx 需要在调用 B 函数前后保持一致。
1 | func A: |
调用者保存寄存器:
1 | func A: |
如上图所示,寄存器 %rbx 是由函数 B 的调用者,即函数 func A 来保存并且恢复的。函数 B 感知不到这个情况,可以尽情使用寄存器 %rbx。
被调用者保存寄存器:
1 | func A: |
如图所示,寄存器 %rbx 是由被调用函数,即函数 B 来保存并回复的。函数 A 感知不到这个情况。
不同的寄存器有不同的保存策略。
callee saved(被调用者保存):
%rbx ,%rbp,%r12,%r13,%r14,%r15
caller saved(调用者保存):
%rax,%rdi,%rsi,%rdx,%rcx,%8,%r9,%r10,%r11
定理内容:
a为自然数,p为一个质数。则有
ap≡a (mod p)
其中 ≡ 是同模符号,表示左右的数字对于p来说取模,是相等的。
证明:
数学归纳法
(a+1)p−(a+1)=k=0∑pCpkak1p−k−a−1=Cp0a01p+k=1∑p−1Cpkak1p−k+Cppap10−a−1=1+k=1∑p−1Cpkak1p−k+ap−a−1=k=1∑p−1Cpkak1p−k+ap−a
因为Cpk=k!(p−k)!p!并且p为质数,所以p为∑k=1p−1Cpkak1p−k的因数,即 p ∣∑k=1p−1Cpkak1p−k。
又因为由假设2可知p为ap−a的因数。所以p为∑k=1p−1Cpkak1p−k+ap−a的因数,即为(a+1)p−(a+1)的因数。证毕。
应用:
如果a不是p的倍数,那么还有
ap−1≡1 (mod p)
所以可以用上式解决一些问题,如计算2100模13。
因为2不是13的倍数,则213−1≡1(mod 13)。
2100=212∗8+4 (mod 13)=(212)8∗24 (mod 13)=18∗24 (mod 13)=16 (mod 13)=3
reference:
1 | #include<sys/types.h> |
ET:
ET模式下需要一次性处理完所有数据,下次就不会加入到epoll_wait的事件中了。
LT:
LT模式下未处理完的事件还是会被加入到epoll_wait监听的事件中。
reference:
linux高性能服务器编程——游双P153-P157