模板
佳木斯大学张丰波
文章目录
阶乘
int num[1000000] = {1}, len = 1;
int mult(int num[], int len, int n) {
long long tmp = 0;
for(long long i = 0; i < len; i++) {
tmp += num[i] * n;
num[i] = tmp % 10;
tmp /= 10;
}
while(tmp) {
num[len++] = tmp % 10;
tmp /= 10;
}
return len;
}
int main() {
int n;
cin >> n;
for(int i = 2; i <= n; i++) {
len = mult(num, len, i);
}
for(int i = len - 1; i >= 0; i--) {
printf("%d", num[i]);
}
return 0;
}
大数相加
vector<int>add(vector<int>&A, vector<int>&B) {
int t = 0;
vector<int>C;
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() {
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');
auto C = add(A, B);
for(int i = C.size() - 1; i >= 0; i--) {
cout << C[i];
}
cout << endl;
return 0;
}
大数相减
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;
}
vector<int>mul(vector<int>&A, vector<int>&B) {
int t = 0;
vector<int>C;
for(int i = 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;
cin >> a >> b;
vector<int>A, B, C;
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');
if(cmp(A, B)) {
C = mul(A, B);
} else {
cout << "-";
C = mul(B, A);
}
for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
cout << endl;
return 0;
}
大数乘法
高精度乘低精度
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--) {
cout << C[i];
}
return 0;
}
大数除法
高精度除低精度
vector<int>div(vector<int>&A, int b, int &r) {
vector<int>C;
r = 0;
for(int i = A.size() - 1; i >= 0; i--) {
r = r * 10 + A[i];
C.push_back(r / b);
r %= b;
}
reverse(C.begin(), C.end());
while(C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main() {
string a;
int b, r;
cin >> a >> b;
vector<int>A, C;
for(int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0');
C = div(A, b, r);
for(int i = C.size() - 1; i >= 0; i--) cout << C[i];
cout << endl << r << endl;
return 0;
}
快速幂
sum = 2 ^ n , sum 的位数 n *
log10
(2) + 1
int qpow(long long a, long long b) { //qpowmod(ll a, ll b, ll m)
long long ans = 1, base = a; //base = a % m;
while(b > 0) {
if(b & 1) {
ans *= base; //ans = ans * base % m;
}
base *= base; //base = base * base % m
b >>= 1;
}
return ans; //ans % m
}
快排
const int N = 1e6 + 7;
int q[N];
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) {
do i++; while(q[i] < x);
do j --;while(q[j] > x);
if(i < j)swap(q[i], q[j]);
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
归并排序
const int N = 1e6 + 7;
int q[N], temp[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 i = l, j = mid + 1, k = 0;
while(i <= mid && j <= r) {
if(q[i] < q[j]) temp[k++] = q[i++];
else temp[k++] = q[j++];
}
while(i <= mid) temp[k++] = q[i++];
while(j <= r) temp[k++] = q[j++];
for(int i = l, j = 0; i <= r; i++, j++)q[i] = temp[j];
}
逆序数
给定一个数组A[0…N-1], 若对于某元素a[i],a[j],若i < j且a[i] > a[j], 则称为(a[i], a[j])为逆序对。一个数组中包含逆序对的数目成为该数组的逆序数。
while(i <= mid && j <= r) {
if(q[i] < q[j]) temp[k++] = q[i++];
else {
count += (mid - i + 1);//修改归并排序的merge函数
temp[k++] = q[j++];
}
}
//特别注意的是当多组数输入的时候count要初始化为0;
冒泡排序
const int N = 1e6 + 7;
int q[N], n;
void bubble_sort(int q[]) {
for(int i = 0; i < n - 1; i++) {
for(int j = 0; j < n - i - 1; j++) {
if(q[j] > q[j + 1]) {
swap(q[j], q[j + 1]);
}
}
}
return;
}
欧几里德
int gcd(int a, int b) {
return a == 0 ? b : gcd(b % a, a);
}
c = __gcd(a, b);
l = a / c * b ;
拓展欧几里德
int ex_gcd(int a, int b, int *x, int *y) {
if (!b) {
*x = 1, *y = 0;
return a;
}
int ret = ex_gcd(b, a % b, y, x);//y = 下一层的&x', x = 下一层的&y';
//*y = x', *x = y'
*y -= a / b * (*x);
return ret;
}
int main() {
int a, b, x, y;
while (~scanf("%d%d", &a, &b)) {
printf("gcd(%d, %d) = %d\n", a, b, ex_gcd(a, b, &x, &y));
printf("%d * %d + %d * %d = %d\n", a, x, b, y, a * x + b * y);
}
return 0;
}
树状数组
#define lowbit(x) ((x) & (-x))
#define MAX_N 200005
long long c[MAX_N + 5] = {0};
long long n;
void add(long long x, long long val) {
while(x <= n) {
c[x] += val;
x += lowbit(x);
}
}
long long getsum(long long x) {
long long sum = 0;
while(x) {
sum += c[x];
x -= lowbit(x);
}
return sum;
}
1 . 单点更新与区间求和
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
int a;
cin >> a;
add(i, a);
}
for(int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
if(a == 1) {
add(b, c);//将某一个数上加上c
}
if(a == 2) {
cout << getsum(c) - getsum(b - 1) << endl;//求出[b, c]区间每一个数的和
}
}
return 0;
}
- 区间更新与单点求值
int main() {
cin >> n >> m;
int now = 0;
for(int i = 1; i <= n; i++) {
int a;
cin >> a;
add(i, a - now);
now = a;
}
for(int i = 1; i <= m; i++) {
int a;
cin >> a;
if(a == 1) {
int x, y, z;
cin >> x >> y >> z;
add(x, z);//将某区间
add(y + 1, -z); //每一个数都加上x;
}
if(a == 2) {
int x;
cin >> x;
cout << getsum(x) << endl;//求出某一个数的值
}
}
return 0;
}
快速读如
inline int read() {
register int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-')f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
快速输出
inline void write(register int x) {
int x < 0{
putchar('-');
x = -x;
}
if(x > 9) {
write(x / 10);
}
putchar(x % 10 + '0');
}
优先队列
#include<queue> //p.top()
priority_queue<int, vector<int>, greater<int> >p//从小到大
priority_queue<int>p; //从大到小
结构体_priority
#include<queue>
struct Node{
int value;
int key;
}p[10];
struct cmp{
bool operator()(Node a, Node b) {
if(a.key == b.key) {
return a.value < b.value;
}
return a.key < b.key;//注意和sort分开
}
};
priority_queue<Node, vector<Node>, cmp> heap;//按第一关键字 从大到小排序
实现优先队列
#include<vector>
template <class type>
class priority_queue{
private:
vector<type> data;
public:
void push(type t) {
data.push_back(t);
push_heap(data.begin(), data.end());
}
void pop() {
pop_heap(data,begin(), data.end());
data.pop_back();
}
type top() {return data.front();}
int size() { return data.size();}
bool empty() {return data.empty();}
}
全排列
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int ans[4] = {1, 2, 3, 4};
sort(ans, ans + 4);
do {//如果是while循环,要提前输出
for(int i = 0;i < 4; i++) {
cout << ans[i] << " ";
}
cout << endl;
}while(next_permutation(ans, ans + 4));
return 0;
}
int n, num[15], cnt, vis[15];
void func(int s) {
if(s == n) {
for(int i = 0; i < cnt; i++) {
i && cout << " ";
cout << num[i];
}
cout << endl;
}
for(int i = 1; i <= n; i++) {
if(!vis[i]) {
vis[i] = 1;
num[cnt++] = i;//此处可以i改为a[i]
func(s + 1);
cnt --;
vis[i] = 0;
}
}
}
int main() {
cin >> n;
func(0);
return 0;
}
递归实现指数型枚举
输入:
3
输出:
1
1 2
1 2 3
1 3
2
2 3
3
int num[15], cnt, n;
void p() {
for(int i = 0; i < cnt ; i++) {
if(i) cout << " ";
cout << num[i];
}
cout << endl;
}
void f(int s) {
for(int i = s; i <= n; i++) {
num[cnt++] = i;
p();
f(i + 1);
cnt--;
}
}
int main() {
cin >> n;
f(1);
return 0;
}
递归实现组合型枚举
输入:
3 2
输出:
1 2
1 3
2 3
int n, m, cnt, ans[20];
void dfs(int s) {
if(cnt == m) {
for(int i = 0; i < cnt; i++) {
i && cout << " ";
cout << ans[i];
}
cout << endl;
}
for(int i = s; i <= n; i++) {
ans[cnt++] = i;
dfs(i + 1);
cnt--;
}
}
int main() {
cin >> n >> m;
dfs(1);
return 0;
}
递归实现排列型枚举
int n, num[15], cnt, vis[15];
void func(int left) {
if(left == n) {
for(int i = 0; i < cnt; i++) {
i && cout << " ";
cout << num[i];
}
cout << endl;
}
for(int i = 1; i <= n; i++) {
if(!vis[i]) {
vis[i] = 1;
num[cnt++] = i;
func(left + 1);
cnt --;
vis[i] = 0;
}
}
}
int main() {
cin >> n;
func(0);
return 0;
}
二分搜索
const int N = 1e6+7;
int a[N];
int x, n;
int binary_search(int a[], int l, int r) {
while(l < r) {
int mid = (l + r) >> 1;//直接使用(l+r) /2 可能会导致溢出,可以使用
//int mid = (r - l) / 2 + l;防止溢出
if(a[mid] == x) {
return mid;
} else if(a[mid] > x) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return -1;
}
int main() {
cin >> n >> x;
for(int i = 0; i < n; i++) {
cin >> a[i];
}
cout << binary_search(a, 0, n - 1) << endl;
return 0;
}
二分变形
bool check(int x){/*...*/}//检查x是否满足某种性质
//区间[l, r]被划分为[l, mid]和[mid + 1, r]时使用:
//0 0 0 0 1 1 1 1,找第一个1
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]时使用:
//1 1 1 1 0 0 0 0//找最后一个1
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;
}
浮点二分–类似牛顿迭代法
bool check(double x) {/*...*/}//检查x是否满足某种性质
double bsearch_3(double l, double r) {
const double esp = 1e-6;//调精度
while(r - l > eps) {
double mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid;
}
return l;
}
线性筛
const int N = 1e6 + 7;
int prime[N];
void is_prime() {
for(int i = 2; i <= N; i++) {
if(!prime[i]) {
prime[++prime[0]] = i;
}
for(int j = 1; j <= prime[0]; j++) {
if(i * prime[j] > N) break;
prime[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
}
并查集
int f[10010];
int find(int k) {
if(f[k] == k) return k;
return f[k] = find(f[k]);
}
void join(int x, int y) {
int fx = find(x);
int fy = find(y);
f[fx] = fy;
}
for(int i = 1;i <= 100; i++) {
f[i] = i;
}//切记 f数组一定初始化为自己为自己父亲
01背包
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
int all , n, w[105], v[105], ans[105][1000005];
int main() {
cin >> all >> n;
for (int i = 1; i <= n; i++) {
cin >> w[i] >> v[i];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= all; j++) {
if (j < w[i]) {
ans[i][j] = ans[i - 1][j];
} else {
ans[i][j] = max(ans[i- 1][j], ans[i - 1][j - w[i]] + v[i]);
}
}
}
cout << ans[n][all] << endl;
return 0;
}