快排
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j)
{
while (q[++ i] < x);
while (q[-- j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
二分
整数二分
算法思路:假设目标值在闭区间[l, r]
中, 每次将区间长度缩小一半,当l = r
时,我们就找到了目标值。
bool check(int x) {/* ... */} // 检查x是否满足某种性质
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
二分的应用
[HTML_REMOVED]lower_bound
和upper_bound
函数的实现[HTML_REMOVED]
[HTML_REMOVED]二分的总结[HTML_REMOVED]
浮点数二分
// 浮点数二分算法模板
bool check(double x) {/* ... */} // 检查x是否满足某种性质
double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
位运算
求n的第k位数字: n >> k & 1
返回n的最后一位1:lowbit(n) = n & -n x -= lowbit(n) // 去除n的最后一位1
归并排序
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], tmp[N];
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
merge_sort(a, 0, n - 1);
for (int i = 0; i < n; i ++ ) printf("%d ", a[i]);
return 0;
}
高精度
加法
t+=a[i]+b[i]; c.push_back(t%10); t/=10
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
vector<int> add(vector<int> &a,vector<int> &b){
vector<int> c;
int t=0;//进位
for(int i=0;i<a.size() || i<b.size();i++){
if(i<a.size()) t+=a[i];
if(i<b.size()) t+=b[i];
c.push_back(t%10);
t/=10;//进位权重下降
}
if(t) c.push_back(1);
return c;
}
int main(){
vector<int> a,b;
string A,B;
cin>>A>>B;
for(int i=A.size()-1;i>=0;i--) a.push_back(A[i]-'0');
for(int i=B.size()-1;i>=0;i--) b.push_back(B[i]-'0');
vector<int> c=add(a,b);
for(int i=c.size()-1;i>=0;i--) printf("%d",c[i]);
return 0;
}
减法
利用cmp比较大小
t=a[i]-t
;t -=b[i]
;if (t<0)
; t=1
;else t = 0
#include <iostream>
#include <vector>
using namespace std;
bool cmp(vector<int> &A, vector<int> &B)
{
if (A.size() != B.size()) return A.size() > B.size();
for (int i = A.size() - 1; i >= 0; i -- )
if (A[i] != B[i])
return A[i] > B[i];
return true;
}
// s大数减小数
vector<int> sub(vector<int> &A, vector<int> &B)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size(); i ++ )
{
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a, b;
vector<int> A, B;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
vector<int> C;
if (cmp(A, B)) C = sub(A, B);
else C = sub(B, A), cout << '-';
for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
cout << endl;
return 0;
}
乘法
t+=a[i]*b
;c.push_back(t%10)
;t/=10
高精乘低精
#include <iostream>
#include <vector>
using namespace std;
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a;
int b;
cin >> a >> b;
vector<int> A;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
auto C = mul(A, b);
for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
return 0;
}
高精乘高精
#include <iostream>
#include <vector>
using namespace std;
vector<int> mul(vector<int> &A, vector<int> &B) {
vector<int> C(A.size() + B.size(), 0); // 初始化为 0,且999*99最多 5 位
for (int i = 0; i < A.size(); i++)
for (int j = 0; j < B.size(); j++)
C[i + j] += A[i] * B[j];
int t = 0;
for (int i = 0; i < C.size(); i++) { // i = C.size() - 1时 t 一定小于 10
t += C[i];
C[i] = t % 10;
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back(); // 必须要去前导 0,因为最高位很可能是 0
return C;
}
int main() {
string a, b;
cin >> a >> b; // a = "1222323", b = "2323423423"
vector<int> A, B;
for (int i = a.size() - 1; i >= 0; i--)
A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--)
B.push_back(b[i] - '0');
auto C = mul(A, B);
for (int i = C.size() - 1; i >= 0; i--)
cout << C[i];
return 0;
}
除法
r=r*10+ a[i]
;c.push_back(r/b)
;r%=b
#include <iostream>
#include <vector>
using namespace std;
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a;
int b;
cin >> a >> b;
vector<int> A;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
auto C = mul(A, b);
for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
return 0;
}
前缀和差分
..................
离散化
vectotr<int> alls;
存储所有待离散化的值
sort(alls.begin(),alls.end());
将所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end())
去除重复元素
// 二分求出x对应的离散化的值
int find(int x) {
int l = 0, r = alls.size() - 1;
while(l < r) {
int mid = l + r >> 1;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + l; // 如果要求前缀和下标映射到1,2,3...n
}
快速幂
int main() {
long long a, b, ans = 1, k;
cin >> a >> b >> k;
while(b) {
if (b & 1) ans = ans * a % k;
a = a * a % k;
b >>= 1;
}
if(k == 1) ans = 0;
cout << a
}