2019-09-11  2024-09-15    8849 字  18 分钟
CF

Codeforces Template

VIM

 1syntax on
 2set cindent
 3set nu
 4set tabstop=4
 5set shiftwidth=4
 6set background=dark
 7 
 8map <C-A> ggVG"+y
 9map <F5> :call Run()<CR>
10func! Run()
11	exec "w"
12	exec "!g++ -Wall % -o %<"
13	exec "!./%<"
14endfunc
1#!/bin/bash
2
3for name in {A..M};
4do
5    cp a.cpp $name.cpp
6done
 1filetype plugin indent on
 2colorscheme desert
 3syntax on
 4set nu
 5set backspace=2
 6set hlsearch 
 7set syntax=on
 8set tabstop=4
 9set shiftwidth=4
10set smarttab
11set smartindent
12set showmatch
13set matchtime=0
14set report=0
15:inoremap ( ()<ESC>i
16:inoremap [ []<ESC>i
17:inoremap { {}<ESC>i
18:inoremap {<CR> {<CR>}<ESC>O
19:inoremap ) <c-r>=Close(')')<CR>
20:inoremap ] <c-r>=Close(']')<CR>
21:inoremap } <c-r>=Close('}')<CR>
22function Close(char)
23    if getline('.')[col('.') - 1] == a:char
24        return "\<Right>"
25    else
26        return a:char
27    endif
28endfunction
29
30map <C-A> ggVG"+y
31map <F5> :call Run()<CR>
32func! Run()
33    exec "w"
34    exec "!g++-7 -O2 -std=c++11 -Wall % -o %<"
35    exec "!./%<"
36endfunc
37
38map <F12> :call SetTitle()<CR>
39func SetTitle()
40let l = 0
41let l = l + 1 | call setline(l,'/* ***********************************************')
42let l = l + 1 | call setline(l,'Author        : Akvicor')
43let l = l + 1 | call setline(l,'Created Time  : '.strftime('%c'))
44let l = l + 1 | call setline(l,'File Name     : '.expand('%'))
45let l = l + 1 | call setline(l,'************************************************ */')
46let l = l + 1 | call setline(l,'')
47
48let l = l + 1 | call setline(l,'#include <bits/stdc++.h>')
49let l = l + 1 | call setline(l,'')
50let l = l + 1 | call setline(l,'#define FAST_IO ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);')
51let l = l + 1 | call setline(l,'')
52let l = l + 1 | call setline(l,'using namespace std;')
53let l = l + 1 | call setline(l,'')
54let l = l + 1 | call setline(l,'int main(){')
55let l = l + 1 | call setline(l,'    FAST_IO;')
56let l = l + 1 | call setline(l,'    ')
57let l = l + 1 | call setline(l,'    return 0;')
58let l = l + 1 | call setline(l,'}')
59endfunc

快速幂

1LL quick_pow(LL a, LL b, LL p) {
2	LL res = 1 % p;
3	for (; b; b >>= 1) {
4		if (b & 1) res = res * a % p;
5		a = a * a % p;
6	}
7	return res;
8}

快速乘

 1// O(1)
 2ll mul(ll a, ll b, ll p) {
 3	return ((__int128)a*b)%p;
 4}
 5// O(1)
 6ll mul(ll a, ll b, ll p) {
 7	a %= p; b %= p;
 8	ll c = (long double)a * b / p;
 9	ll ans = a * b - c * p;
10	return (ans % p + p) % p;
11}
12// O(log)
13ll mul(ll a, ll b, ll p) {
14	ll ans = 0;
15	while (b) {
16		if (b & 1) ans = (ans + a) % p;
17		a = a * 2 % p;
18		b >>= 1;
19	}
20	return ans;
21}

欧拉φ函数

 1int GetEuler(int n) {  //欧拉函数
 2     int res = n;
 3     for(int i = 2;i*i <= n; ++i){
 4         if(a%i == 0){
 5             res -= res/i; 
 6             while(n%i == 0) 
 7                 n /= i;
 8         }
 9     }
10     if(a > 1) // 因为是遍历到sqrt(n),所以可能存在未除尽或者n本身就为质数的情况
11         res -= res/n;
12     return res;
13}
14
15int Phi(int x) {  //欧拉函数
16    int i, re = x;
17    for (i = 2; i * i <= x; i++)
18        if (x % i == 0) {
19            re /= i;
20            re *= i - 1;
21            while (x % i == 0)
22                x /= i;
23        }
24    if (x ^ 1) re /= x, re *= x - 1;
25    return re;
26}

欧拉函数线性筛

 1const int MAXN = 1e6;
 2//欧拉线性筛:在线性时间内筛素数的同时求出所有数的欧拉函数
 3int tot;
 4int phi[MAXN]; //保存各个数字的欧拉函数
 5int prime[MAXN]; //按顺序保存素数
 6bool mark[MAXN]; //判断是否是素数
 7void get_phi(int N){
 8    phi[1] = 1;
 9    for(int i = 2; i <= MAXN; i++){ //相当于分解质因数的逆过程
10        if(!mark[i]){
11            prime[++tot] = i;
12            phi[i] = i-1;
13        }
14        for(int j = 1; j <= tot; j++){
15            if(i * prime[j] > N) break;
16            mark[i * prime[j]] = 1; //确定i*prime[j]不是素数
17            if(i % prime[j] == 0){ //判断prime[j] 是否为 i的约数
18                phi[i * prime[j]] = phi[i] * prime[j];
19                break;
20            }
21            else{ //prime[j] - 1 就是 phi[prime[j]],利用了欧拉函数的积性
22                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
23            }
24        }
25    }
26}

Green公式-判断多边形边界曲线顺/逆时针

1double d = 0;
2for (int i = 0; i < n - 1; i++) {
3    d += -0.5 * ( y[i + 1] + y[i]) * (x[i + 1] - x[i]);
4}
5if ( d > 0)
6    cout << "counter clockwise" << endl;
7else
8    cout << "clockwise" << endl;

dijkstra

 1const int INF = 0x3f3f3f3f;
 2#define maxn 1000+100
 3int path[maxn][maxn], dis[maxn]; // 地图  起点到达i的距离
 4bool vis[maxn]; // 是否访问过
 5int n, t; //  地标数  路径数
 6
 7void init() {
 8    for (int i = 0; i < maxn; ++i) {
 9        for (int j = 0; j < maxn; ++j) {
10            path[i][j] = INF;
11        }
12        path[i][i] = 0;
13    }
14}
15
16void dijkstra(){
17    // 将1到i的距离初始化
18    for (int i = 1; i <= n; i++) {
19        dis[i] = path[1][i];
20        vis[i] = false;
21    }
22    vis[1] = true; // 标记起点为访问过的
23    dis[1] = 0; // 起点到起点的距离为0
24    for (int i = 2; i <= n; i++) { // 从2号节点遍历到n号节点
25        int now = -1, minL = INF;
26        // 遍历一遍dis数组,寻找到未访问过的到1最短的路径长度
27        for (int j = 1; j <= n; j++) { // 从1到n
28            if (!vis[j] && minL > dis[j]) { // 如果没有访问过当前节点,并且当前从1到j的距离小于最大长度
29                now = j; // 更新最短路径的位置
30                minL = dis[j]; // 最短距离等于当前
31            }
32        }
33        if (now == -1) break; // 未找到
34        vis[now] = true; // 将now标记为访问过
35        // 从1开始寻找到j最短的路径
36        for (int j = 1; j <= n; j++) {
37            // 没有访问过 并且当前已走的长度加上走到j节点的长度小于当前dis[j]
38            if (!vis[j] && (dis[now] + path[now][j]) < dis[j]) {
39                dis[j] = dis[now] + path[now][j]; // 更新从起点到j的最短路径
40            }
41        }
42    }
43}
44
45int main() {
46    freopen("in.txt", "r", stdin); // 从指定文件输入数据 提交时注释掉
47//    memset(path, INT_MAX, sizeof(path));
48    while (scanf("%d %d", &n, &t) != EOF) {
49        init();
50        for (int i = 0; i < t; i++) {
51            int from, to, len;
52            scanf("%d %d %d", &from, &to, &len);
53            if (path[from][to] > len)
54                path[from][to] = path[to][from] = len;
55        }
56        dijkstra();
57        for (int i = 1; i <= n; i++) {
58            printf("1 to %d min= %d\n", i, dis[i]);
59        }
60    }
61    return 0;
62}

素性测试

 1bool is_prime(int n){  /* 判定一个数是不是素数 ,假设输入的数都是正整数 */
 2    for (int i = 2; i * i <= n; i++) {
 3        if (!(n % i)) return false;
 4    }
 5    return n != 1;  /* 1是例外 */
 6}
 7
 8
 9const int S = 8;
10
11LL mult_mod(LL a, LL b, LL c){
12	a %= c;
13	b %= c;
14	LL ret = 0;
15	LL tmp = a;
16	while(b){
17		if(b&1){
18			ret += tmp;
19			if(ret > c) ret -= c;
20		}
21		tmp <<= 1;
22		if(tmp > c) tmp -= c;
23		b >>= 1;
24	}
25	return ret;
26}
27
28LL pow_mod(LL a, LL n, LL mod){
29	LL ret = 1;
30	LL temp = a % mod;
31	while(n){
32		if(n & 1) ret = mult_mod(ret, temp, mod);
33		temp = mult_mod(temp, temp, mod);
34		n >>= 1;
35	}
36	return ret;
37}
38
39bool check(LL a, LL n, LL x, LL t){
40	LL ret = pow_mod(a, x, n);
41	LL last = ret;
42	loop(i, 1, t){
43		ret = mult_mod(ret, ret, n);
44		if(ret == 1 && last != 1 && last != n-1) return true;
45		last = ret;
46	}
47	if(ret != 1) return true;
48	else return false;
49}
50
51bool Miller_Rabin(LL n){
52	if(n < 2) return false;
53	if(n == 2) return true;
54	if((n&1)==0) return false;
55	LL x = n-1;
56	LL t = 0;
57	while((x&1)==0){x >>= 1; ++t;}
58	srand(time(NULL));
59	rep(i, S){
60		LL a = rand()%(n-1)+1;
61		if(check(a, n, x, t)) return false;
62	}
63	return true;
64}

埃氏筛法

 1bool is_prime[100];
 2int prime[100];
 3int sieve(int n) { /* 枚举n以内的素数 */
 4    /*  返回n以内素数的个数,素数存在prime数组里  */
 5    int p = 0;
 6    for (int i = 0; i <= n; i++)
 7        is_prime[i] = true;
 8    is_prime[0] = is_prime[1] = false;
 9    for (int i = 2; i <= n; i++) {
10        if (is_prime[i]) {
11            prime[p++] = i;
12            for (int j = i * 2; j <= n; j += i)
13                is_prime[j] = false;
14        }
15    }
16    return p;
17}

区间筛法

 1#define M 100000000
 2typedef long long ll;
 3bool is_prime_small[M];
 4bool is_prime[M];
 5ll ans = 0;
 6
 7void prime(ll a, ll b) {
 8    for (ll i = 2; i * i < b; i++) is_prime_small[i] = true; //初始化2~b^(1/2)
 9    for (ll i = 0; i < b - a; i++) is_prime[i] = true; //因为a,b很大,所以用0~b-a 代表a~b
10    for (ll i = 2; i * i < b; i++) {
11        if (is_prime_small[i]) {
12            for (ll j = 2 * i; j * j < b; j += i) is_prime_small[j] = false;
13            for (ll j = max(2LL, (a + i - 1) / i) * i; j < b; j += i) { //找到从a开始的第一个合数
14                if (is_prime[j - a]) {
15                    ans++; //求出几个合数。  //或者也可以最后遍历b-a这区间,求出质数的个数。
16                    is_prime[j - a] = false;
17                }
18            }
19        }
20    }
21}
22
23int main() {
24    ll a, b;
25    ans = 0;
26    cin >> a >> b;
27    prime(a, b);
28    // for(ll i = 0;i < b-a;i++)
29    //    if(is_prime[i]) ans++;
30    cout << "ans = " << b - a - ans << endl;
31    return 0;
32}

线段树

 1class SegmentTree{
 2
 3private:
 4    int * tree;
 5    int N;
 6
 7public:
 8    int * temp;
 9
10    SegmentTree(unsigned int n){
11        tree = new int [(n<<2u) +10u];
12        temp = new int [(n<<2u) +10u];
13        this->N = n;
14    }
15
16    ~SegmentTree(){
17        delete[] tree;
18        delete[] temp;
19    }
20
21    /**
22     * 建树
23     */
24    void init(){
25        build(1, 1, this->N);
26    }
27
28    /**
29     * 建树
30     * @param p p树
31     * @param l 区间左端点
32     * @param r 区间右端点
33     */
34    void build(int p, int l, int r){
35        if(l == r){
36            tree[p] = temp[l];
37            return;
38        }
39        int mid = l + (r - l) / 2;
40        build(p * 2, l, mid);
41        build(p * 2 + 1, mid + 1, r);
42        tree[p] = tree[p * 2] + tree[p * 2 + 1];
43    }
44
45    /**
46     * 更新
47     * @param p 当前节点编号
48     * @param l 区间左界
49     * @param r 区间右界
50     * @param x 需要修改的节点编号
51     * @param num 操作
52     */
53    void change(int p, int l, int r, int x, int num){
54        if(l == r){
55            tree[p] += num;
56            if(tree[p]<0) tree[p] = 0;
57            return;
58        }
59        int mid = l + (r - l) / 2;
60        if(x <= mid) change(p * 2, l, mid, x, num);
61        else change(p * 2 + 1, mid + 1, r, x, num);
62        tree[p] = tree[p * 2] + tree[p * 2 + 1];
63    }
64
65
66    /**
67     * 查询
68     * @param p 在p这棵树
69     * @param l p的左区间端点
70     * @param r p的右区间端点
71     * @param x 查询区间左端点
72     * @param y 查询区间右端点
73     * @return 区间和
74     */
75    int find(int p, int l, int r, int x, int y){
76        if(x <= l && r <= y) return tree[p];
77        int mid = l + (r - l) / 2;
78        if(y <= mid) return find(p * 2, l, mid, x, y);
79        if(x > mid) return find(p * 2 + 1, mid + 1, r, x, y);
80        return find(p * 2, l, mid, x, mid) + find(p * 2 + 1, mid + 1, r, mid + 1, y);
81    }
82
83};

最大子列和问题

 1int maxsequence3(int a[], int len)
 2{
 3    int maxsum, maxhere;
 4    maxsum = maxhere = a[0]; //初始化最大和为a【0】
 5    for (int i=1; i<len; i++) {
 6        if (maxhere <= 0)
 7            maxhere = a[i]; //如果前面位置最大连续子序列和小于等于0,则以当前位置i结尾的最大连续子序列和为a[i]
 8        else
 9            maxhere += a[i]; //如果前面位置最大连续子序列和大于0,则以当前位置i结尾的最大连续子序列和为它们两者之和
10        if (maxhere > maxsum) {
11            maxsum = maxhere; //更新最大连续子序列和
12        }
13    }
14    return maxsum;
15}

约数个数定理

 1int f1(int n) {
 2    int r = (int) sqrt(1.0 * n);
 3    int sum = 0;
 4    if (r * r == n) {
 5        sum++;
 6        r--;
 7    }
 8    for (int i = 1; i <= r; i++)
 9        if (n % i == 0) {
10            sum += 2;
11        }
12    cout << sum << endl;
13}
14
15// 稍快于f1
16int f2(int n){
17    int s = 1, r;
18    for (int i = 2; i * i <= n; i++) {
19        r = 0;
20        while (n % i == 0) {
21            r++;
22            n /= i;
23        }
24        if (r > 0) {
25            r++;
26            s *= r;
27        }
28    }
29    if (n > 1)
30        s *= 2;
31    cout << s << endl;
32}
33
34ll f3(ll n) {
35    ll res=1;
36    for(ll i=2;i*i<=n;i++){
37        ll k=0;
38        while(n%i == 0){
39            n = n/i;
40            k++;
41        }
42        if(k) res *= (k+1);
43    }
44    if(n != 1) res=res*2;
45    if(res==1){
46        if(n==1) return 1;
47        else return 2;
48    }
49    cout << res << endl;
50}

约数和定理

 1ll qpow(ll x, ll y) {
 2    ll res = 1;
 3    while (y) {
 4        if (y & 1) res *= x;
 5        x *= x;
 6        y >>= 1;
 7    }
 8    return res;
 9}
10
11ll getsum(ll n) {//返回n的约数和是多少.
12    ll res = 1;
13    for (ll i = 2; i * i <= n; i++) {
14        ll k = 0;
15        while (n % i == 0) {
16            n = n / i;
17            k++;
18        }
19        res *= ((1 - qpow(i, k + 1)) / (1 - i));
20    }    //用等比数列公式(快速幂)算.
21    if (n != 1) res *= (1 + n);
22    cout << res << endl;
23}

大整数

  1#include <bits/stdc++.h>
  2using namespace std;
  3// base and base_digits must be consistent
  4constexpr int base = 1000000000;
  5constexpr int base_digits = 9;
  6
  7struct bigint {
  8    // value == 0 is represented by empty z
  9    vector<int> z; // digits
 10
 11    // sign == 1 <==> value >= 0
 12    // sign == -1 <==> value < 0
 13    int sign;
 14
 15    bigint() : sign(1) {}
 16    bigint(long long v) { *this = v; }
 17
 18    bigint &operator=(long long v) {
 19        sign = v < 0 ? -1 : 1; v *= sign;
 20        z.clear(); for (; v > 0; v = v / base) z.push_back((int) (v % base));
 21        return *this;
 22    }
 23
 24    bigint(const string &s) { read(s); }
 25
 26    bigint &operator+=(const bigint &other) {
 27        if (sign == other.sign) {
 28            for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) {
 29                if (i == z.size())
 30                    z.push_back(0);
 31                z[i] += carry + (i < other.z.size() ? other.z[i] : 0);
 32                carry = z[i] >= base;
 33                if (carry)
 34                    z[i] -= base;
 35            }
 36        } else if (other != 0 /* prevent infinite loop */) {
 37            *this -= -other;
 38        }
 39        return *this;
 40    }
 41
 42    friend bigint operator+(bigint a, const bigint &b) { return a += b; }
 43
 44    bigint &operator-=(const bigint &other) {
 45        if (sign == other.sign) {
 46            if (sign == 1 && *this >= other || sign == -1 && *this <= other) {
 47                for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) {
 48                    z[i] -= carry + (i < other.z.size() ? other.z[i] : 0);
 49                    carry = z[i] < 0;
 50                    if (carry)
 51                        z[i] += base;
 52                }
 53                trim();
 54            } else {
 55                *this = other - *this;
 56                this->sign = -this->sign;
 57            }
 58        } else {
 59            *this += -other;
 60        }
 61        return *this;
 62    }
 63
 64    friend bigint operator-(bigint a, const bigint &b) { return a -= b; }
 65
 66    bigint &operator*=(int v) {
 67        if (v < 0) sign = -sign, v = -v;
 68        for (int i = 0, carry = 0; i < z.size() || carry; ++i) {
 69            if (i == z.size())
 70                z.push_back(0);
 71            long long cur = (long long) z[i] * v + carry;
 72            carry = (int) (cur / base);
 73            z[i] = (int) (cur % base);
 74        }
 75        trim();
 76        return *this;
 77    }
 78
 79    bigint operator*(int v) const { return bigint(*this) *= v; }
 80
 81    friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
 82        int norm = base / (b1.z.back() + 1);
 83        bigint a = a1.abs() * norm;
 84        bigint b = b1.abs() * norm;
 85        bigint q, r;
 86        q.z.resize(a.z.size());
 87
 88        for (int i = (int) a.z.size() - 1; i >= 0; i--) {
 89            r *= base;
 90            r += a.z[i];
 91            int s1 = b.z.size() < r.z.size() ? r.z[b.z.size()] : 0;
 92            int s2 = b.z.size() - 1 < r.z.size() ? r.z[b.z.size() - 1] : 0;
 93            int d = (int) (((long long) s1 * base + s2) / b.z.back());
 94            r -= b * d;
 95            while (r < 0)
 96                r += b, --d;
 97            q.z[i] = d;
 98        }
 99
100        q.sign = a1.sign * b1.sign;
101        r.sign = a1.sign;
102        q.trim();
103        r.trim();
104        return {q, r / norm};
105    }
106
107    friend bigint sqrt(const bigint &a1) {
108        bigint a = a1;
109        while (a.z.empty() || a.z.size() % 2 == 1)
110            a.z.push_back(0);
111
112        int n = a.z.size();
113
114        int firstDigit = (int) ::sqrt((double) a.z[n - 1] * base + a.z[n - 2]);
115        int norm = base / (firstDigit + 1);
116        a *= norm;
117        a *= norm;
118        while (a.z.empty() || a.z.size() % 2 == 1)
119            a.z.push_back(0);
120
121        bigint r = (long long) a.z[n - 1] * base + a.z[n - 2];
122        firstDigit = (int) ::sqrt((double) a.z[n - 1] * base + a.z[n - 2]);
123        int q = firstDigit;
124        bigint res;
125
126        for (int j = n / 2 - 1; j >= 0; j--) {
127            for (;; --q) {
128                bigint r1 = (r - (res * 2 * base + q) * q) * base * base +
129                            (j > 0 ? (long long) a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0);
130                if (r1 >= 0) {
131                    r = r1;
132                    break;
133                }
134            }
135            res *= base;
136            res += q;
137
138            if (j > 0) {
139                int d1 = res.z.size() + 2 < r.z.size() ? r.z[res.z.size() + 2] : 0;
140                int d2 = res.z.size() + 1 < r.z.size() ? r.z[res.z.size() + 1] : 0;
141                int d3 = res.z.size() < r.z.size() ? r.z[res.z.size()] : 0;
142                q = (int) (((long long) d1 * base * base + (long long) d2 * base + d3) / (firstDigit * 2));
143            }
144        }
145
146        res.trim();
147        return res / norm;
148    }
149
150    bigint operator/(const bigint &v) const { return divmod(*this, v).first; }
151
152    bigint operator%(const bigint &v) const { return divmod(*this, v).second; }
153
154    bigint &operator/=(int v) {
155        if (v < 0) sign = -sign, v = -v;
156        for (int i = (int) z.size() - 1, rem = 0; i >= 0; --i) {
157            long long cur = z[i] + rem * (long long) base;
158            z[i] = (int) (cur / v);
159            rem = (int) (cur % v);
160        }
161        trim();
162        return *this;
163    }
164
165    bigint operator/(int v) const { return bigint(*this) /= v; }
166
167    int operator%(int v) const {
168        if (v < 0) v = -v;
169        int m = 0;
170        for (int i = (int) z.size() - 1; i >= 0; --i)
171            m = (int) ((z[i] + m * (long long) base) % v);
172        return m * sign;
173    }
174
175    bigint &operator*=(const bigint &v) { return *this = *this * v; }
176    bigint &operator/=(const bigint &v) { return *this = *this / v; }
177
178    bool operator<(const bigint &v) const {
179        if (sign != v.sign)
180            return sign < v.sign;
181        if (z.size() != v.z.size())
182            return z.size() * sign < v.z.size() * v.sign;
183        for (int i = (int) z.size() - 1; i >= 0; i--)
184            if (z[i] != v.z[i])
185                return z[i] * sign < v.z[i] * sign;
186        return false;
187    }
188
189    bool operator>(const bigint &v) const { return v < *this; }
190    bool operator<=(const bigint &v) const { return !(v < *this); }
191    bool operator>=(const bigint &v) const { return !(*this < v); }
192
193    bool operator==(const bigint &v) const { return !(*this < v) && !(v < *this); }
194
195    bool operator!=(const bigint &v) const { return *this < v || v < *this; }
196
197    void trim() {
198        while (!z.empty() && z.back() == 0) z.pop_back();
199        if (z.empty()) sign = 1;
200    }
201
202    bool isZero() const { return z.empty(); }
203
204    friend bigint operator-(bigint v) {
205        if (!v.z.empty()) v.sign = -v.sign;
206        return v;
207    }
208
209    bigint abs() const {
210        return sign == 1 ? *this : -*this;
211    }
212
213    long long longValue() const {
214        long long res = 0;
215        for (int i = (int) z.size() - 1; i >= 0; i--)
216            res = res * base + z[i];
217        return res * sign;
218    }
219
220    friend bigint gcd(const bigint &a, const bigint &b) {
221        return b.isZero() ? a : gcd(b, a % b);
222    }
223
224    friend bigint lcm(const bigint &a, const bigint &b) {
225        return a / gcd(a, b) * b;
226    }
227
228    void read(const string &s) {
229        sign = 1;
230        z.clear();
231        int pos = 0;
232        while (pos < s.size() && (s[pos] == '-' || s[pos] == '+')) {
233            if (s[pos] == '-')
234                sign = -sign;
235            ++pos;
236        }
237        for (int i = (int) s.size() - 1; i >= pos; i -= base_digits) {
238            int x = 0;
239            for (int j = max(pos, i - base_digits + 1); j <= i; j++)
240                x = x * 10 + s[j] - '0';
241            z.push_back(x);
242        }
243        trim();
244    }
245
246    friend istream &operator>>(istream &stream, bigint &v) {
247        string s; stream >> s;
248        v.read(s);
249        return stream;
250    }
251
252    friend ostream &operator<<(ostream &stream, const bigint &v) {
253        if (v.sign == -1)
254            stream << '-';
255        stream << (v.z.empty() ? 0 : v.z.back());
256        for (int i = (int) v.z.size() - 2; i >= 0; --i)
257            stream << setw(base_digits) << setfill('0') << v.z[i];
258        return stream;
259    }
260
261    static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
262        vector<long long> p(max(old_digits, new_digits) + 1);
263        p[0] = 1;
264        for (int i = 1; i < p.size(); i++)
265            p[i] = p[i - 1] * 10;
266        vector<int> res;
267        long long cur = 0;
268        int cur_digits = 0;
269        for (int v : a) {
270            cur += v * p[cur_digits];
271            cur_digits += old_digits;
272            while (cur_digits >= new_digits) {
273                res.push_back(int(cur % p[new_digits]));
274                cur /= p[new_digits];
275                cur_digits -= new_digits;
276            }
277        }
278        res.push_back((int) cur);
279        while (!res.empty() && res.back() == 0)
280            res.pop_back();
281        return res;
282    }
283
284    typedef vector<long long> vll;
285
286    static vll karatsubaMultiply(const vll &a, const vll &b) {
287        int n = a.size();
288        vll res(n + n);
289        if (n <= 32) {
290            for (int i = 0; i < n; i++)
291                for (int j = 0; j < n; j++)
292                    res[i + j] += a[i] * b[j];
293            return res;
294        }
295
296        int k = n >> 1;
297        vll a1(a.begin(), a.begin() + k);
298        vll a2(a.begin() + k, a.end());
299        vll b1(b.begin(), b.begin() + k);
300        vll b2(b.begin() + k, b.end());
301
302        vll a1b1 = karatsubaMultiply(a1, b1);
303        vll a2b2 = karatsubaMultiply(a2, b2);
304
305        for (int i = 0; i < k; i++)
306            a2[i] += a1[i];
307        for (int i = 0; i < k; i++)
308            b2[i] += b1[i];
309
310        vll r = karatsubaMultiply(a2, b2);
311        for (int i = 0; i < a1b1.size(); i++)
312            r[i] -= a1b1[i];
313        for (int i = 0; i < a2b2.size(); i++)
314            r[i] -= a2b2[i];
315
316        for (int i = 0; i < r.size(); i++)
317            res[i + k] += r[i];
318        for (int i = 0; i < a1b1.size(); i++)
319            res[i] += a1b1[i];
320        for (int i = 0; i < a2b2.size(); i++)
321            res[i + n] += a2b2[i];
322        return res;
323    }
324
325    bigint operator*(const bigint &v) const {
326        vector<int> a6 = convert_base(this->z, base_digits, 6);
327        vector<int> b6 = convert_base(v.z, base_digits, 6);
328        vll a(a6.begin(), a6.end());
329        vll b(b6.begin(), b6.end());
330        while (a.size() < b.size())
331            a.push_back(0);
332        while (b.size() < a.size())
333            b.push_back(0);
334        while (a.size() & (a.size() - 1))
335            a.push_back(0), b.push_back(0);
336        vll c = karatsubaMultiply(a, b);
337        bigint res;
338        res.sign = sign * v.sign;
339        for (int i = 0, carry = 0; i < c.size(); i++) {
340            long long cur = c[i] + carry;
341            res.z.push_back((int) (cur % 1000000));
342            carry = (int) (cur / 1000000);
343        }
344        res.z = convert_base(res.z, 6, base_digits);
345        res.trim();
346        return res;
347    }
348
349};
350
351bigint random_bigint(int n) {
352    string s;
353    for (int i = 0; i < n; i++) {
354        s += rand() % 10 + '0';
355    }
356    return bigint(s);
357}
358
359// random tests
360void bigintTest() {
361    bigint x = bigint("120");
362    bigint y = bigint("5");
363    cout << x / y << endl;
364
365    for (int i = 0; i < 1000; i++) {
366        int n = rand() % 100 + 1;
367        bigint a = random_bigint(n);
368        bigint res = sqrt(a);
369        bigint xx = res * res;
370        bigint yy = (res + 1) * (res + 1);
371
372        if (xx > a || yy <= a) {
373            cout << i << endl;
374            cout << a << " " << res << endl;
375            break;
376        }
377
378        int m = rand() % n + 1;
379        bigint b = random_bigint(m) + 1;
380        res = a / b;
381        xx = res * b;
382        yy = b * (res + 1);
383
384        if (xx > a || yy <= a) {
385            cout << i << endl;
386            cout << a << " " << b << " " << res << endl;
387            break;
388        }
389    }
390
391    bigint a = random_bigint(10000);
392    bigint b = random_bigint(2000);
393    clock_t start = clock();
394    bigint c = a / b;
395    printf("time=%.3lfsec\n", (clock() - start) * 1. / CLOCKS_PER_SEC);
396}
397
398string str(bigint b) {
399    stringstream ss; ss << b;
400    string s; ss >> s;
401    return s;
402}

并查集

  1namespace UF1{
  2
  3    class UnionFind{
  4
  5    private:
  6        int* parent; // parent[i]表示第i个元素所指向的父节点
  7        int* sz;     // sz[i]表示以i为根的集合中元素个数
  8        int count;   // 数据个数
  9
 10    public:
 11        // 构造函数
 12        UnionFind(int count){
 13            parent = new int[count];
 14            sz = new int[count];
 15            this->count = count;
 16            for( int i = 0 ; i < count ; i ++ ){
 17                parent[i] = i;
 18                sz[i] = 1;
 19            }
 20        }
 21
 22        // 析构函数
 23        ~UnionFind(){
 24            delete[] parent;
 25            delete[] sz;
 26        }
 27
 28        // 查找过程, 查找元素p所对应的集合编号
 29        // O(h)复杂度, h为树的高度
 30        int find(int p){
 31            assert( p >= 0 && p < count );
 32            // 不断去查询自己的父亲节点, 直到到达根节点
 33            // 根节点的特点: parent[p] == p
 34            while( p != parent[p] )
 35                p = parent[p];
 36            return p;
 37        }
 38
 39        // 查看元素p和元素q是否所属一个集合
 40        // O(h)复杂度, h为树的高度
 41        bool isConnected( int p , int q ){
 42            return find(p) == find(q);
 43        }
 44
 45        // 合并元素p和元素q所属的集合
 46        // O(h)复杂度, h为树的高度
 47        void unionElements(int p, int q){
 48
 49            int pRoot = find(p);
 50            int qRoot = find(q);
 51
 52            if( pRoot == qRoot )
 53                return;
 54
 55            // 根据两个元素所在树的元素个数不同判断合并方向
 56            // 将元素个数少的集合合并到元素个数多的集合上
 57            if( sz[pRoot] < sz[qRoot] ){
 58                parent[pRoot] = qRoot;
 59                sz[qRoot] += sz[pRoot];
 60            }
 61            else{
 62                parent[qRoot] = pRoot;
 63                sz[pRoot] += sz[qRoot];
 64            }
 65        }
 66    };
 67}
 68
 69
 70namespace UF2{
 71
 72    class UnionFind{
 73
 74    private:
 75        int* rank;   // rank[i]表示以i为根的集合所表示的树的层数
 76        int* parent; // parent[i]表示第i个元素所指向的父节点
 77        int count;   // 数据个数
 78
 79    public:
 80        // 构造函数
 81        UnionFind(int count){
 82            parent = new int[count];
 83            rank = new int[count];
 84            this->count = count;
 85            for( int i = 0 ; i < count ; i ++ ){
 86                parent[i] = i;
 87                rank[i] = 1;
 88            }
 89        }
 90
 91        // 析构函数
 92        ~UnionFind(){
 93            delete[] parent;
 94            delete[] rank;
 95        }
 96
 97        // 查找过程, 查找元素p所对应的集合编号
 98        // O(h)复杂度, h为树的高度
 99        int find(int p){
100            assert( p >= 0 && p < count );
101            // 不断去查询自己的父亲节点, 直到到达根节点
102            // 根节点的特点: parent[p] == p
103            while( p != parent[p] )
104                p = parent[p];
105            return p;
106        }
107
108        // 查看元素p和元素q是否所属一个集合
109        // O(h)复杂度, h为树的高度
110        bool isConnected( int p , int q ){
111            return find(p) == find(q);
112        }
113
114        // 合并元素p和元素q所属的集合
115        // O(h)复杂度, h为树的高度
116        void unionElements(int p, int q){
117
118            int pRoot = find(p);
119            int qRoot = find(q);
120
121            if( pRoot == qRoot )
122                return;
123
124            // 根据两个元素所在树的元素个数不同判断合并方向
125            // 将元素个数少的集合合并到元素个数多的集合上
126            if( rank[pRoot] < rank[qRoot] ){
127                parent[pRoot] = qRoot;
128            }
129            else if( rank[qRoot] < rank[pRoot]){
130                parent[qRoot] = pRoot;
131            }
132            else{ // rank[pRoot] == rank[qRoot]
133                parent[pRoot] = qRoot;
134                rank[qRoot] += 1;   // 此时, 我维护rank的值
135            }
136        }
137    };
138}

直线划分平面

1while(cin>>n)
2    cout<<n*(n+1)/2+1<<endl;

判断两个线段相交

 1# 点
 2class Point(object):
 3
 4    def __init__(self, x, y):
 5        self.x, self.y = x, y
 6
 7# 向量
 8class Vector(object):
 9
10    def __init__(self, start_point, end_point):
11        self.start, self.end = start_point, end_point
12        self.x = end_point.x - start_point.x
13        self.y = end_point.y - start_point.y
14
15
16ZERO = 1e-9
17
18def negative(vector):
19    """取反"""
20    return Vector(vector.end_point, vector.start_point)
21
22def vector_product(vectorA, vectorB):
23    '''计算 x_1 * y_2 - x_2 * y_1'''
24    return vectorA.x * vectorB.y - vectorB.x * vectorA.y
25
26def is_intersected(A, B, C, D):
27    '''A, B, C, D  Point 类型'''
28    AC = Vector(A, C)
29    AD = Vector(A, D)
30    BC = Vector(B, C)
31    BD = Vector(B, D)
32    CA = negative(AC)
33    CB = negative(BC)
34    DA = negative(AD)
35    DB = negative(BD)
36
37    return (vector_product(AC, AD) * vector_product(BC, BD) <= ZERO) \
38        and (vector_product(CA, CB) * vector_product(DA, DB) <= ZERO)

网络流

  1struct Flow_Dinic {
  2        Flow_Dinic(int n) {
  3            head = vector<int>(n + 10, -1);
  4            level = vector<int>(n + 10);
  5        }
  6
  7        struct edge {
  8            int to, cap, next;
  9        };
 10
 11        vector<int> head;
 12        vector<int> level;
 13
 14        int s = 0, t = 0; // max_flow from s to t
 15
 16        vector<struct edge> edge;
 17
 18        void add_edge(int u, int v, int c) {
 19            edge.push_back((struct edge) {v, c, head[u]});
 20            head[u] = edge.size() - 1;
 21            edge.push_back((struct edge) {u, 0, head[v]});
 22            head[v] = edge.size() - 1;
 23        }
 24
 25        bool bfs() {
 26            fill(level.begin(), level.end(), 0);
 27            level[s] = 1;
 28            queue<int> que;
 29            que.push(s);
 30            while (!que.empty()) {
 31                for (int i = head[que.front()]; ~i; i = edge[i].next) {
 32                    if (edge[i].cap && !level[edge[i].to]) {
 33                        level[edge[i].to] = level[que.front()] + 1;
 34                        que.push(edge[i].to);
 35                        if (edge[i].to == t) return true;
 36                    }
 37                }
 38                que.pop();
 39            }
 40            return false;
 41        }
 42
 43        int dfs(int f, int u) {
 44            if (u == t) return f;
 45            int d = 0, used = 0;
 46            for (int i = head[u]; ~i; i = edge[i].next) {
 47                if (edge[i].cap && level[u] == level[edge[i].to] - 1) {
 48                    if ((d = dfs(min(f - used, edge[i].cap), edge[i].to))) {
 49                        edge[i].cap -= d;
 50                        edge[i ^ 1].cap += d;
 51                        used += d;
 52                    }
 53                }
 54            }
 55            if (!used) level[u] = 0;
 56            return used;
 57        }
 58
 59        long long run(int _s, int _t) {
 60            s = _s;
 61            t = _t;
 62            long long max_flow = 0;
 63            while (bfs()) {
 64                int d = 0;
 65                while ((d = dfs(0x3f3f3f3f, s))) max_flow += d;
 66            }
 67            return max_flow;
 68        }
 69    };
 70
 71
 72struct Dinic {
 73    Dinic(int n) {
 74        G = vector<vector<int> >(n + 10);
 75        d = vector<int> (n+10);
 76        vis = vector<bool> (n+10);
 77        cur = vector<int> (n+10);
 78    }
 79
 80    struct Edge {
 81        int from, to, cap, flow;
 82    };
 83
 84    int s, t; //节点数,边数,源点编号,汇点编号
 85    vector<Edge> edges; //边表,edges[e]和edges[e^1]互为反向弧
 86    vector<vector<int> > G; //邻接表,G[i][j]表示节点i的第j条边在e中的序号
 87    vector<bool> vis; //bfs用
 88    vector<int> d; //从起点到i的距离
 89    vector<int> cur; //当前弧下标
 90    void add_edge(int from, int to, int cap) {
 91        edges.push_back({from, to, cap, 0});
 92        edges.push_back({to, from, 0, 0});
 93        G[from].push_back(edges.size() - 2);
 94        G[to].push_back(edges.size() - 1);
 95    }
 96
 97    bool BFS() {
 98        fill(vis.begin(), vis.end(), false);
 99        queue<int> q;
100        q.push(s);
101        d[s] = 0;
102        vis[s] = true;
103        while (!q.empty()) {
104            for (int id : G[q.front()]) {
105                Edge &e = edges[id];
106                if (!vis[e.to] && e.cap > e.flow) {
107                    vis[e.to] = true;
108                    d[e.to] = d[q.front()] + 1;
109                    q.push(e.to);
110                }
111            }
112            q.pop();
113        }
114        return vis[t];
115    }
116
117    long long DFS(int u, int a) {
118        if (u == t || a == 0) return a;
119        int flow = 0, f;
120        for (int &i = cur[u]; i < (int) G[u].size(); ++i) {
121            Edge &e = edges[G[u][i]];
122            if (d[u] + 1 == d[e.to] &&
123                (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
124                e.flow += f;
125                edges[G[u][i] ^ 1].flow -= f;
126                flow += f;
127                a -= f;
128                if (a == 0) break;
129            }
130        }
131        return flow;
132    }
133
134    long long run(int _s, int _t) {
135        s = _s;
136        t = _t;
137        long long flow = 0;
138        while (BFS()) {
139            fill(cur.begin(), cur.end(), 0);
140            flow += DFS(s, 0x3f3f3f3f);
141        }
142        return flow;
143    }
144};

最大子矩阵

  1MOD(1e9+7);
  2MAXN(1010);
  3
  4int mp[MAXN][MAXN], l[MAXN], r[MAXN];
  5priority_queue <int> ans;
  6
  7void solve(){
  8    FAST_IO;
  9    
 10    int n, m;
 11	cin >> n >> m;
 12	loop(i, 1, n) loop(j, 1, m){
 13		char c; cin >> c;
 14		mp[i][j] = (c == '1');
 15	}
 16	loop(i, 2, n) loop(j, 1, m)
 17		if(mp[i-1][j] && mp[i][j]) mp[i][j] += mp[i-1][j];
 18	loop(i, 1, n){
 19		set<pair<int, PII> > S;
 20		stack<int> A, B;
 21		loop(j, 1, m){
 22			while(!A.empty() && mp[i][A.top()] >= mp[i][j]) A.pop();
 23			l[j] = A.size() ? A.top()+1 : 1;
 24			A.push(j);
 25		}
 26		for(int j = m; j >= 1; --j){
 27			while(!B.empty() && mp[i][B.top()] >= mp[i][j]) B.pop();
 28			r[j] = B.size() ? B.top() - 1 : m;
 29			B.push(j);
 30		}
 31		loop(j, 1, m){
 32			if(mp[i][j]){
 33				pair<int, PII> temp = mp(r[j], mp(l[j], mp[i][j]));
 34				pair<int ,PII> temp2;
 35				if(!S.count(temp)){
 36					ans.push((r[j] - l[j]+1)*mp[i][j]);
 37					S.insert(temp);
 38				}
 39				if(r[j] - l[j]){
 40					temp = mp(r[j], mp(l[j]+1, mp[i][j]));
 41					temp2 = mp(r[j]-1, mp(l[j], mp[i][j]));
 42					if(!S.count(temp)){
 43						ans.push((r[j] - l[j]) * mp[i][j]);
 44						S.insert(temp);
 45					}else if(S.count(temp2)){
 46						ans.push((r[j]-l[j])*mp[i][j]);
 47						S.insert(temp2);
 48					}
 49				}
 50			}
 51		}
 52	}
 53	if(ans.size()<2) ans.push(0);
 54	ans.pop();
 55	cout << ans.top() << endl;
 56    
 57}
 58
 59
 60// 速度更快,但只能求前几大
 61
 62MOD(1e9+7);
 63MAXN(1e3);
 64
 65int n, m;
 66string s;
 67int high[MAXN];
 68
 69int mxx, mxx2;
 70int stkhg[MAXN], stkpos[MAXN];
 71int cnt;
 72
 73void solve(){
 74    FAST_IO;
 75    
 76    cin >> n >> m;
 77	high[m+1] = 0;
 78	loop(i, 1, n){
 79		cout << ">-- Line #" << i << " --<" << endl;
 80		cin >> s;
 81		loop(j, 1, m) high[j] = s[j-1]=='0' ? 0 : high[j]+1;
 82#ifdef DEBUG
 83		cout << "str: " << s << endl;
 84		cout << "high: ";
 85		loop(j, 1, m+1) cout << high[j] << ' ';
 86		cout << endl;
 87#endif
 88		stkhg[0] = stkpos[0] = cnt = 0;
 89		loop(j, 1, m+1){
 90			if(high[j] > stkhg[cnt]){ // 如果比上一格高,说明可以构成矩形,就push进栈
 91				stkhg[++cnt] = high[j];
 92				stkpos[cnt] = j;
 93			}else if(high[j] < stkhg[cnt]){ // 如果比上一格矮,
 94				// 那么高度等于上一格高度的矩形已经完全找出来了,
 95				// 当前格比上一格矮,不能参与构成上个矩形
 96				while(high[j] < stkhg[cnt]){ // 将栈中高于当前位置的高度全部出栈
 97					int area = (j-stkpos[cnt]) * stkhg[cnt]; // 当前位置坐标-比当前格高的格的坐标就是宽度
 98					// 更新前两大矩形
 99					if(area >= mxx){
100						mxx2 = mxx;
101						mxx = area;
102						mxx2 = max(mxx2, max(area-stkhg[cnt], area-(j-stkpos[j])));
103					}else if(area > mxx2){
104						mxx2 = area;
105					}
106					--cnt;
107				}
108				if(stkhg[cnt] != high[j]){
109					stkhg[++cnt] = high[j];
110				}
111			}
112#ifdef DEBUG
113			cout << j << " stkhg: ";
114			loop(j, 1, m+1) cout << stkhg[j] << ' ';
115			cout << endl;
116			cout << j << " stkpos: ";
117			loop(j, 1, m+1) cout << stkpos[j] << ' ';
118			cout << endl;
119			cout << "mxx: " << mxx << " mxx2: " << mxx2 << endl;
120#endif
121		}
122	}
123	cout << mxx2 << endl;
124    
125}

拓展欧几里得

$_math_inline$ax+by=\gcd(a, b)$math_inline_$
 1void exgcd(LL a, LL b, LL &x, LL &y) {
 2	if (b == 0) {
 3		x = 1;y = 0;
 4	} else {
 5		exgcd(b, a%b, y, x);
 6		y -= (a/b) * x;
 7	}
 8}
 9
10void extgcd(LL a, LL b, LL &d, LL &x, LL &y) {
11    if (!b) {
12        d = a;        
13        x = 1;
14        y = 0;
15    } else {
16        extgcd(b, a % b, d, y, x);
17        y -= x * (a / b);
18    }
19}
20
21LL inverse(LL a, LL n) {
22    LL d, x, y;
23    extgcd(a, n, d, x, y);
24    return d == 1 ? (x + n) % n : -1;
25}

递推求1~n的逆元

1const int N = 1e5 + 5;
2int inv[N];
3
4void inverse(int n, int p) {
5    inv[1] = 1;
6    for (int i = 2; i <= n; ++i) {
7        inv[i] = (ll) (p - p / i) * inv[p % i] % p;
8    }
9}

递推求n!的逆元

 1// 快速幂求逆元
 2int quick_inverse(int n, int p) {
 3	int ret = 1;
 4	int exponent = p - 2;
 5	for (int i = exponent; i; i >>= 1, n = n * n % p) {
 6		if (i & 1) {
 7			ret = ret * n % p;
 8		}
 9	} 
10	return ret;
11}
12int invf[N], factor[N];
13void get_factorial_inverse(int n, int p) {
14	factor[0] = 1;
15	for (int i = 1; i <= n; ++i) {
16		factor[i] = i * factor[i - 1] % p;
17	}
18	invf[n] = quick_inverse(factor[n], p);
19	for (int i = n-1; i >= 0; --i) {
20		invf[i] = invf[i + 1] * (i + 1) % p;
21	}
22}

lowbit

1lowbit(n) = n&(~n+1) = n&(-n)

数的那些位为1

1void f2(int n){
2    int H[37];
3    for(int i = 0; i < 36; ++i) H[(1ll << i) % 37] = i;
4    while(n > 0){
5        cout << H[(n & -n) % 37] << ' ';
6        n -= n & -n;
7    }
8    cout << endl;
9}

最短Hamilton路径

 1int f[1 << 20][20], weight[20][20], n;
 2
 3int hamilton(int n, int weight[20][20]) {
 4	memset(f, 0x3f, sizeof(f));
 5	f[1][0] = 0;
 6	for (int i = 1; i < 1 << n; i++)
 7		for (int j = 0; j < n; j++) if (i >> j & 1)
 8			for (int k = 0; k < n; k++) if ((i^1<<j) >> k & 1)
 9				f[i][j] = min(f[i][j], f[i^1<<j][k]+weight[k][j]);
10	return f[(1 << n) - 1][n - 1];
11}
12
13int main() {
14	cin >> n;
15	for(int i = 0; i < n; i++)
16		for(int j = 0; j < n; j++)
17			scanf("%d", &weight[i][j]);
18	cout << hamilton(n, weight) << endl;
19}

卡特兰数

前三十项卡特兰数表

1[1,1,2,5,14,42,132,429,1430,4862,16796,58786,
2 208012,742900,2674440,9694845,35357670,129644790,
3 477638700,1767263190,6564120420,24466267020,
4 91482563640,343059613650,1289904147324,
5 4861946401452,18367353072152,69533550916004,
6 263747951750360,1002242216651368,3814986502092304]

卡特兰数求模模板

 1const int C_maxn = 1e4 + 10;
 2LL CatalanNum[C_maxn];
 3LL inv[C_maxn];
 4inline void Catalan_Mod(int N, LL mod)
 5{
 6    inv[1] = 1;
 7    for(int i=2; i<=N+1; i++)///线性预处理 1 ~ N 关于 mod 的逆元
 8        inv[i] = (mod - mod / i) * inv[mod % i] % mod;
 9
10    CatalanNum[0] = CatalanNum[1] = 1;
11
12    for(int i=2; i<=N; i++)
13        CatalanNum[i] = CatalanNum[i-1] * (4 * i - 2) %mod * inv[i+1] %mod;
14}

卡特兰大数模板

 1#include<bits/stdc++.h>
 2using namespace std;
 3const int C_maxn = 100 + 10;///项数
 4
 5int Catalan_Num[C_maxn][1000];///保存卡特兰大数、第二维为具体每个数位的值
 6int NumLen[C_maxn];///每个大数的数长度、输出的时候需倒序输出
 7
 8void catalan() //求卡特兰数
 9{
10    int i, j, len, carry, temp;
11    Catalan_Num[1][0] = NumLen[1] = 1;
12    len = 1;
13    for(i = 2; i < 100; i++)
14    {
15        for(j = 0; j < len; j++) //乘法
16        Catalan_Num[i][j] = Catalan_Num[i-1][j]*(4*(i-1)+2);
17        carry = 0;
18        for(j = 0; j < len; j++) //处理相乘结果
19        {
20            temp = Catalan_Num[i][j] + carry;
21            Catalan_Num[i][j] = temp % 10;
22            carry = temp / 10;
23        }
24        while(carry) //进位处理
25        {
26            Catalan_Num[i][len++] = carry % 10;
27            carry /= 10;
28        }
29        carry = 0;
30        for(j = len-1; j >= 0; j--) //除法
31        {
32            temp = carry*10 + Catalan_Num[i][j];
33            Catalan_Num[i][j] = temp/(i+1);
34            carry = temp%(i+1);
35        }
36        while(!Catalan_Num[i][len-1]) //高位零处理
37        len --;
38        NumLen[i] = len;
39    }
40}
41
42int main(void)
43{
44    catalan();
45    for(int i=1; i<=30; i++){
46        for(int j=NumLen[i]-1; j>=0; j--){
47            printf("%d", Catalan_Num[i][j]);
48        }puts("");
49    }
50    return 0;
51}

除另有声明外本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可转载请注明原作者与文章出处