基础算法---模板总结

模板

佳木斯大学张丰波

阶乘

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;
}

欧几里德

image-20200922141128255
int gcd(int a, int b) {
    return a == 0 ? b : gcd(b % a, a);
}
c = __gcd(a, b);
l = a / c * b ;

拓展欧几里德

image-20200922142047836
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;
}
  1. 区间更新与单点求值
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;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值