常用模板 UPD12/4

基础算法

二分

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;   //写r=mid,不需要+1
        // 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;//如果写l=mid,需要+1
        else r = mid - 1;
    }
    return l;
}

数据结构

邻接表

int h[N],e[N],ne[N],idx = 0; 

void add(int a, int b) {
	e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}


memset(h,-1,sizeof(h));
  • 二维—邻接表
int h[N];//存所有的链表头
int e[N];//存所有的边->每个节点值
int ne[N];//存所有的节点的next是多少,节点i的下一个节点在哪里
int idx = 0; //存储当前用到了哪个点

void add_to_head(int a, int b) { //在a所对应的单链表中插入节点b  e.g.(2,3)在2所对应的邻接表中插入节点3 对应图中2->3有一条有向边
	e[idx] = b; // 给节点三赋值
	ne[idx] = h[a];
	h[a] = idx++;
	//这样存,e[idx]的实际邻接表是乱序的,需要h[a],ne[],e[]的帮助输出有序序列
}

链表

int head = -1;
int e_one_dimension[N];
int ne_one_dimension[N];
int idx_one_dimension = 0;

void add_to_head_one_dimension(int x) {
	e_one_dimension[idx_one_dimension] = x;
	ne[idx_one_dimension] = head; //head初值为-1
	head = idx_one_dimension++;
}

STL

vector, 变长数组,倍增的思想
    size()  返回元素个数
    empty()  返回是否为空
    clear()  清空
    front()/back()
    push_back()/pop_back()
    begin()/end()
    []
    支持比较运算,按字典序

pair<int, int>
    first, 第一个元素
    second, 第二个元素
    支持比较运算,以first为第一关键字,以second为第二关键字(字典序)

string,字符串
    size()/length()  返回字符串长度
    empty()
    clear()
    substr(起始下标,(子串长度))  返回子串
    c_str()  返回字符串所在字符数组的起始地址

queue, 队列
    size()
    empty()
    push()  向队尾插入一个元素
    front()  返回队头元素
    back()  返回队尾元素
    pop()  弹出队头元素

priority_queue, 优先队列,默认是大根堆
    size()
    empty()
    push()  插入一个元素
    top()  返回堆顶元素
    pop()  弹出堆顶元素
    定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;

stack,size()
    empty()
    push()  向栈顶插入一个元素
    top()  返回栈顶元素
    pop()  弹出栈顶元素

deque, 双端队列
    size()
    empty()
    clear()
    front()/back()
    push_back()/pop_back()
    push_front()/pop_front()
    begin()/end()
    []

set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列
    size()
    empty()
    clear()
    begin()/end()
    ++, -- 返回前驱和后继,时间复杂度 O(logn)

    set/multiset
        insert()  插入一个数
        find()  查找一个数
        count()  返回某一个数的个数
        erase()
            (1) 输入是一个数x,删除所有x   O(k + logn)
            (2) 输入一个迭代器,删除这个迭代器
        lower_bound()/upper_bound()
            lower_bound(x)  返回大于等于x的最小的数的迭代器
            upper_bound(x)  返回大于x的最小的数的迭代器
    map/multimap
        insert()  插入的数是一个pair
        erase()  输入的参数是pair或者迭代器
        find()
        []  注意multimap不支持此操作。 时间复杂度是 O(logn)
        lower_bound()/upper_bound()

unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表
    和上面类似,增删改查的时间复杂度是 O(1)
    不支持 lower_bound()/upper_bound(), 迭代器的++--

bitset, 圧位
    bitset<10000> s;
    ~, &, |, ^
    >>, <<
    ==, !=
    []

    count()  返回有多少个1

    any()  判断是否至少有一个1
    none()  判断是否全为0

    set()  把所有位置成1
    set(k, v)  将第k位变成v
    reset()  把所有位变成0
    flip()  等价于~
    flip(k) 把第k位取反

输入输出优化

参考代码

namespace IO {
const int MAXSIZE = 1 << 20;
char buf[MAXSIZE], *p1, *p2;
#define gc()                                                               \
  (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) \
       ? EOF                                                               \
       : *p1++)
inline int rd() {
  int x = 0, f = 1;
  char c = gc();
  while (!isdigit(c)) {
    if (c == '-') f = -1;
    c = gc();
  }
  while (isdigit(c)) x = x * 10 + (c ^ 48), c = gc();
  return x * f;
}
char pbuf[1 << 20], *pp = pbuf;
inline void push(const char &c) {
  if (pp - pbuf == 1 << 20) fwrite(pbuf, 1, 1 << 20, stdout), pp = pbuf;
  *pp++ = c;
}
inline void write(int x) {
  static int sta[35];
  int top = 0;
  do {
    sta[top++] = x % 10, x /= 10;
  } while (x);
  while (top) push(sta[--top] + '0');
}
}  // namespace IO

食用说明

  1. 使用namespace中的函数,加上using namespace IO,如果只想单独调用一个函数,使用using IO::rd类似的rd处填你想要的函数
  2. 读入时使用n = rd()并且在输入结束后加上EOF代表文件输入结束。
    注意:在dev C++中,回车后在单行输入Ctrl Z
template <typename T>
inline void read(T &x) {
    x = 0;
    LL f = 1;
    char c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -1;
    for (; isdigit(c); c = getchar()) x = x * 10 + c - 48;
    x *= f;
}
template <typename T>
inline void write(T x) {
    if(x < 0) {putchar('-'); x = -x;}
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
template <typename T>
inline void writesp(T x, char sp = '\n') {
    write(x); putchar(sp);
}

调试

debug(a)

#define debug(a) cout << #a << " " << a << endl

高精度

高精度PI

const double PI=acos(-1.0);

最大最小值

template<class T>
inline void ckmin(T &a, T b) { if (b < a) a = b; }

template<class T>
inline void ckmax(T &a, T b) { if (b > a) a = b; }

大数模板

已重载的运算符

运算符类型运算符
双目运算符+(加), -(减), *(乘), /(整除), %(取模)
关系运算符==(等于), !=(不等于), <(小于), >(大于), <=(小于等于), >=(大于等于)
逻辑运算符||(逻辑或), &&(逻辑与), !(逻辑非)
单目运算符+(正), -(负)
自增自减运算符++(自增), –(自减)
赋值运算符=, +=, -=, *=, /=, %=
位运算符>>(右移运算符,与输入流关联), <<(左移运算符,与输出流关联)

支持的其他函数

函数声明函数功能
size_t size() const返回 BigInteger 对象的位数
BigInteger e(size_t n) const返回 BigInteger 对象 × $10^n $后的值
BigInteger abs() const返回 BigInteger 对象的绝对值
#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define mod 1000000007
const ll maxn = 2e6 + 7;

//大整数
struct BigInteger {
    static const int BASE = 100000000;//和WIDTH保持一致
    static const int WIDTH = 8;//八位一存储,如修改记得修改输出中的%08d
    bool sign;//符号, 0表示负数
    size_t length;
    vector<int> num;//反序存
//构造函数
    BigInteger(long long x = 0) { *this = x; }

    BigInteger(const string &x) { *this = x; }

    BigInteger(const BigInteger &x) { *this = x; }

//剪掉前导0
    void cutLeadingZero() {
        while (num.back() == 0 && num.size() != 1) { num.pop_back(); }
    }

//设置数的长度
    void setLength() {
        cutLeadingZero();
        int tmp = num.back();
        if (tmp == 0) { length = 1; }
        else {
            length = (num.size() - 1) * WIDTH;
            while (tmp > 0) {
                ++length;
                tmp /= 10;
            }
        }
    }

//赋值运算符
    BigInteger &operator=(long long x) {
        num.clear();
        if (x >= 0) sign = true;
        else {
            sign = false;
            x = -x;
        }
        do {
            num.push_back(x % BASE);
            x /= BASE;
        } while (x > 0);
        setLength();
        return *this;
    }

//赋值运算符
    BigInteger &operator=(const string &str) {
        num.clear();
        sign = (str[0] != '-');//设置符号
        int x, len = (str.size() - 1 - (!sign)) / WIDTH + 1;
        for (int i = 0; i < len; i++) {
            int End = str.length() - i * WIDTH;
            int start = max((int) (!sign), End - WIDTH);//防止越界
            sscanf(str.substr(start, End - start).c_str(), "%d", &x);
            num.push_back(x);
        }
        setLength();
        return *this;
    }

//赋值运算符
    BigInteger &operator=(const BigInteger &tmp) {
        num = tmp.num;
        sign = tmp.sign;
        length = tmp.length;
        return *this;
    }

//将该大数变为一个字符串 
    string tostring() {
        string ans = "";
        for (int i = 0; i < num.size(); i++)
            ans.insert(0, to_string(num[i]));
        if (!sign) ans.insert(0, "-");//负数 
        return ans;
    }

//数的位数
    size_t size() const { return length; }

//*10^n 除法中用到
    BigInteger e(size_t n) const {
        int tmp = n % WIDTH;
        BigInteger ans;
        ans.length = n + 1;
        n /= WIDTH;
        while (ans.num.size() <= n) ans.num.push_back(0);
        ans.num[n] = 1;
        while (tmp--) ans.num[n] *= 10;
        return ans * (*this);
    }

//绝对值
    BigInteger abs() const {
        BigInteger ans(*this);
        ans.sign = true;
        return ans;
    }

//正号
    const BigInteger &operator+() const { return *this; }

// + 运算符
    BigInteger operator+(const BigInteger &b) const {
        if (!b.sign) { return *this - (-b); }
        if (!sign) { return b - (-*this); }
        BigInteger ans;
        ans.num.clear();
        for (int i = 0, g = 0;; i++) {
            if (g == 0 && i >= num.size() && i >= b.num.size()) break;
            int x = g;
            if (i < num.size()) x += num[i];
            if (i < b.num.size()) x += b.num[i];
            ans.num.push_back(x % BASE);
            g = x / BASE;
        }
        ans.setLength();
        return ans;
    }

//负号
    BigInteger operator-() const {
        BigInteger ans(*this);
        if (ans != 0) ans.sign = !ans.sign;
        return ans;
    }

// - 运算符
    BigInteger operator-(const BigInteger &b) const {
        if (!b.sign) { return *this + (-b); }
        if (!sign) { return -((-*this) + b); }
        if (*this < b) { return -(b - *this); }
        BigInteger ans;
        ans.num.clear();
        for (int i = 0, g = 0;; i++) {
            if (g == 0 && i >= num.size() && i >= b.num.size()) break;
            int x = g;
            g = 0;
            if (i < num.size()) x += num[i];
            if (i < b.num.size()) x -= b.num[i];
            if (x < 0) {
                x += BASE;
                g = -1;
            }
            ans.num.push_back(x);
        }
        ans.setLength();
        return ans;
    }

// * 运算符
    BigInteger operator*(const BigInteger &b) const {
        int lena = num.size(), lenb = b.num.size();
        vector<long long> ansLL;
        for (int i = 0; i < lena + lenb; i++) ansLL.push_back(0);
        for (int i = 0; i < lena; i++) {
            for (int j = 0; j < lenb; j++) {
                ansLL[i + j] += (long long) num[i] * (long long) b.num[j];
            }
        }
        while (ansLL.back() == 0 && ansLL.size() != 1) ansLL.pop_back();
        int len = ansLL.size();
        long long g = 0, tmp;
        BigInteger ans;
        ans.sign = (ansLL.size() == 1 && ansLL[0] == 0) || (sign == b.sign);
        ans.num.clear();
        for (int i = 0; i < len; i++) {
            tmp = ansLL[i];
            ans.num.push_back((tmp + g) % BASE);
            g = (tmp + g) / BASE;
        }
        if (g > 0) ans.num.push_back(g);
        ans.setLength();
        return ans;
    }

// / 运算符 (大数除小数)
    BigInteger operator/(const long long &b) const {
        BigInteger c;
        c.num.clear();
        for (int i = 0; i < num.size(); i++) {
            c.num.push_back(0);
        }
        long long g = 0;
        for (int i = num.size() - 1; i >= 0; i--) {
            c.num[i] = (num[i] + g * BASE) / b;
            g = num[i] + g * BASE - c.num[i] * b;
        }
        for (int i = num.size() - 1; c.num[i] == 0; i--) {
            c.num.pop_back();
        }
        return c;
    }

// /运算符 (大数除大数)
    BigInteger operator/(const BigInteger &b) const {
        BigInteger aa((*this).abs());
        BigInteger bb(b.abs());
        if (aa < bb) return 0;
        char *str = new char[aa.size() + 1];
        memset(str, 0, sizeof(char) * (aa.size() + 1));
        BigInteger tmp;
        int lena = aa.length, lenb = bb.length;
        for (int i = 0; i <= lena - lenb; i++) {
            tmp = bb.e(lena - lenb - i);
            while (aa >= tmp) {
                ++str[i];
                aa = aa - tmp;
            }
            str[i] += '0';
        }
        BigInteger ans(str);
        delete[]str;
        ans.sign = (ans == 0 || sign == b.sign);
        return ans;
    }

// % 运算符 (大数取模小数)
    BigInteger operator%(const long long &b) const {
        long long ans = 0, lena = num.size();
        for (int i = lena - 1; i >= 0; i--) {
            ans = (ans * BASE + num[i]) % b;
        }
        return ans;
    }

// %运算符 (大数取模大数)
    BigInteger operator%(const BigInteger &b) const {
        return *this - *this / b * b;
    }

    BigInteger &operator++() {
        *this = *this + 1;
        return *this;
    } // ++ 运算符
    BigInteger &operator--() {
        *this = *this - 1;
        return *this;
    } // -- 运算符
    BigInteger &operator+=(const BigInteger &b) {
        *this = *this + b;
        return *this;
    } // += 运算符
    BigInteger &operator-=(const BigInteger &b) {
        *this = *this - b;
        return *this;
    } // -= 运算符
    BigInteger &operator*=(const BigInteger &b) {
        *this = *this * b;
        return *this;
    } // *=运算符
    BigInteger &operator/=(const long long &b) {
        *this = *this / b;
        return *this;
    } // /=运算符
    BigInteger &operator/=(const BigInteger &b) {
        *this = *this / b;
        return *this;
    } // /= 运算符
    BigInteger &operator%=(const long long &b) {
        *this = *this % b;
        return *this;
    } // %=运算符
    BigInteger &operator%=(const BigInteger &b) {
        *this = *this % b;
        return *this;
    } // %=运算符
// < 运算符
    bool operator<(const BigInteger &b) const {
        if (sign && !b.sign) { return false; }//正负
        else if (!sign && b.sign) { return true; }//负正
        else if (!sign && !b.sign) { return -b < -*this; }//负负
        //正正
        if (num.size() != b.num.size()) return num.size() < b.num.size();
        for (int i = num.size() - 1; i >= 0; i--)
            if (num[i] != b.num[i]) return num[i] < b.num[i];
        return false;
    }

    bool operator>(const BigInteger &b) const { return b < *this; }              // >  运算符
    bool operator<=(const BigInteger &b) const { return !(b < *this); }           // <= 运算符
    bool operator>=(const BigInteger &b) const { return !(*this < b); }           // >= 运算符
    bool operator!=(const BigInteger &b) const { return b < *this || *this < b; }     // != 运算符
    bool operator==(const BigInteger &b) const { return !(b < *this) && !(*this < b); }//==运算符

    bool operator||(const BigInteger &b) const { return *this != 0 || b != 0; } // || 运算符
    bool operator&&(const BigInteger &b) const { return *this != 0 && b != 0; } // && 运算符
    bool operator!() { return (bool) (*this == 0); }                            // ! 运算符

    //重载<<使得可以直接输出大数
    friend ostream &operator<<(ostream &out, const BigInteger &x) {
        if (!x.sign) out << '-';
        out << x.num.back();
        for (int i = x.num.size() - 2; i >= 0; i--) {
            char buf[10];
            //如WIDTH和BASR有变化,此处要修改为%0(WIDTH)d
            sprintf(buf, "%08d", x.num[i]);
            for (int j = 0; j < strlen(buf); j++) out << buf[j];
        }
        return out;
    }

    //重载>>使得可以直接输入大数
    friend istream &operator>>(istream &in, BigInteger &x) {
        string str;
        in >> str;
        size_t len = str.size();
        int i, start = 0;
        if (str[0] == '-') start = 1;
        if (str[start] == '\0') return in;
        for (int i = start; i < len; i++) {
            if (str[i] < '0' || str[i] > '9') return in;
        }
        x.sign = !start;
        x = str.c_str();
        return in;
    }
};

int main() {


    return 0;
}

数学

求C(n,m)

long long C(int n, int m){
	if (m < n - m) m = n - m;
	long long ans = 1;
	for (int i = m + 1; i <= n; i++) ans *= i;
	for (int i = 1; i <= n - m; i++) ans /= i;
	return ans;
}

快速幂

ll qpow(ll a, ll b) {
	ll ans = 1;
	a %= mod;
	assert(b >= 0);
	for(; b; b >>= 1) {
		if(b & 1)ans = ans * a % mod;
		a = a * a % mod;
	}
	return ans;
}

Gcd

ll gcd(ll a, ll b) {
	return b > 0 ? gcd(b, a % b) : a;
}

Exgcd

int exgcd(int a, int b, long long &d, long long &x, long long &y) {
	if(!b)
		d = a, x = 1, y = 0;
	else
		exgcd(b, a % b, d, y, x), y -= (a / b) * x;
}

质数

bool isPrime(int a) {
  if (a < 2) return 0;
  for (int i = 2; i * i <= a; ++i)
    if (a % i) return 0;
  return 1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值