• 【持续更新】算法竞赛常用模板


    一、动态规划

    1. 经典01背包

    问题: 求背包容量允许范围下,装不同物品(每种物品只可取一次)可得到的最高价值

    for(int i=1;i<=n;i++)
    	for(int j=v;j>=c[i];j--)
    		dp[j]=max(dp[j],dp[j-c[i]]+w[i]);

    2. 经典完全背包

    问题: 求背包容量允许范围下,装不同物品(每种物品可取无限次)可得到的最高价值

    for(int i=1;i<=n;i++)
    	for(int j=c[i];j<=v;j--)//必须正序
    		dp[j]=max(dp[j],dp[j-c[i]]+w[i]);

    二、数学

    1. 快速幂

    \(x\)是底数,\(n\)是指数,\(p\)为取模数
    ①普通快速幂

    long long qpow(long long x,long long n,long long p){
    	if(!n)return 1;
    	long long ans=qpow((x%p)*(x%p)%p,n/2,p)%p;
    	if(n%2)ans=ans*(x%p)%p;
    	return ans;
    }
    

    ②矩阵快速幂

    三、图论

    1. 图的存储:

    ①邻接矩阵存边:略
    ②邻接表(vector实现)存边:

    //定义
    struct node{
    	int to;//边通向的点的编号
    	int val;//边权
    }tmp;
    vector<node>edge[MAXN];//MAXN是最大点数
    //加边
    cin>>bh>>tmp.to>>tmp.val;//读入边的起点、终点以及边权
    edge[bh].push(tmp);//给以bh号为起点的边,加一条
    //遍历
    for(int i=0;i<n;i++){
    	int len=edge[i].size();
    	for(int j=0;j<len;j++)
    		……
    }
    

    ③静态链表头插法存边(链式前向星):

    //定义:
    struct node {
        int to,val;//数据域.存储边指向的节点以及边权.
        int nxt;//指针域.假如目前这条边的起点为x,那么nxt则模拟了指针,保存下一个起点同样为x的边的编号
    } edge[MAXM];
    int bh=0;//初始化编号
    memset(head,-1,sizeof(head));//初始化head数组,用-1模拟NULL
    void add(int from,int to,int val) {//加边函数
        edge[++bh].to=to;    //存储边的数据
        edge[bh].val=val;
        edge[bh].nxt=head[from];    //头插法
        head[from]=bh;
    }
    for(int i=head[now]; i!=-1; i=edge[i].nxt){//遍历以now为起点的所有边
        int j=edge[i].to;
    	……
    }

    2. 最短路

    3. 拓扑排序

    4.

    四、数据结构

    1. 并查集:

    2. 最小生成树:

    3. 树状数组:

    基本功能:单点增减(无法将元素修改为某值,这需要线段树来干)、区间求和.
    时间复杂度:\(O_{(nlogn)}\),常数快于线段树
    ①单点增减、区间求和:单点增减直接调用updade函数,区间求和则是sum(right)-sum(left-1)

    //计算lowbit函数
    int lowbit(int x) {
        return x&-x;
    }
    //单点增减
    void update(int val,int bh) {
        int i=bh;
        while(i<=n) {
            c[i]+=val;
            i+=lowbit(i);
        }
    }
    //区间求和
    int sum(int i) {
        int tot=0;
        while(i>0) {
            tot+=c[i];
            i-=lowbit(i);
        }
        return tot;
    }

    ②区间增减、单点求值:树状数组本身与上面一样,只不过建树的时候更新的是差分数组,进行区间增减的时候,update(left,val)以及update(right+1,-val),求和的时候只需求差分数组的前缀和sum(x)
    ③区间增减、区间求和:

    4. ST表:

    5. 线段树:

    6.

    五、杂项

    1.对拍器:

    #include<iostream>
    #include<windows.h>
    using namespace std;
    int main() {
        int t=100;
        while(t) {
            t--;
            system("data.exe > data.txt");
            system("ac1.exe < data.txt > ac1.txt");
            system("t.exe < data.txt > t.txt");
            if(system("fc t.txt ac1.txt"))   break;
        }
        if(t==0) cout<<"no error"<<endl;
        else cout<<"error"<<endl;
        return 0;
    }
  • 相关阅读:
    JAVA基础——编程练习(二)
    JAVA基础——面向对象三大特性:封装、继承、多态
    JVM内存
    50. Pow(x, n) (JAVA)
    47. Permutations II (JAVA)
    46. Permutations (JAVA)
    45. Jump Game II (JAVA)
    43. Multiply Strings (JAVA)
    42. Trapping Rain Water (JAVA)
    41. First Missing Positive (JAVA)
  • 原文地址:https://www.cnblogs.com/yige2019/p/15806272.html
Copyright © 2020-2023  润新知