夏令营复习算法, 感到自己对之前学过的算法略有生疏, 写篇流水账, 权当复习.
- 素数筛法
- 快速幂取模
- 扩展欧几里得/求逆元
素数筛法
一种用已知的小素数 \(p\) 来筛掉更大的合数, 最终留下素数的算法. 实践复杂度 \(O(n\log\log n)\).
实现代码 1: 打标记
1 | const int maxn = 1e6 + 5; |
实现代码 2: 直接存素数
1 | const int maxn = 1e6 + 5; |
事实上也可以先打标记, 再 for
一遍把素数拿出来.
百练 3177: 判决素数个数
总时间限制: 1000ms 内存限制: 65536kB
描述
输入两个整数X和Y,输出两者之间的素数个数(包括X和Y)。
输入
两个整数X和Y(1 <= X,Y <= 105)。
输出
输出一个整数,表示X,Y之间的素数个数(包括X和Y)。
样例输入
1 100
样例输出
25
大致思路
有个坑点… 题目没有保证 \(x\leqslant y\).. 所以需要 swap
一下.
AC代码
1 |
|
扩展欧几里得算法
求解 \(ax+by=d\) 中的 \(x, y\), 其中 \(\gcd(a, b)~|~d\) 才有解.
实现代码
1 | // 返回d = gcd(a, b); 和对应于等式ax + by = d 中的x, y |
快速幂取模
在 \(O(\log n)\) 时间内求 \(a^n~\%m\) 的值.
实现代码
1 | long long pow_mod(int a, int b) |
求逆元
求 \(x\), s.t. \(ax=1~({\rm mod}~m)\).
实现代码 1: 利用扩展欧几里得
1 | // ax = 1 (mod n) |
实现代码 2: 利用费马小定理
由于模数 \(m\) 一般为素数, 当 \((a,m)=1\) 时, 由费马小定理有: \[a^{m-1}=1~({\rm mod}~m)\Rightarrow a^{-1}=a^{m-2}.\] 1
2
3
4long long inv(int a)
{
return pow_mod(a, mod - 2);
}