1.中国剩余定理模板(CRT)

#include <iostream>
using namespace std;

int exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int r = exgcd(b, a % b, x, y);
    int t = x;
    x = y;
    y = t - a / b * y;
    return r;
}

int a[101], m[101];

int CRT(int a[],int m[],int n) {
    int M = 1;
    int ans = 0;
    for(int i = 1;i <= n;i ++) {
        M *= m[i];
    }
    for(int i = 1;i <= n;i ++) {
        int x,y;
        int Mi = M / m[i];
        exgcd(Mi,m[i],x,y);
        ans = (ans + Mi * x * a[i]) % M;
    }
    if(ans < 0) {
        ans += M;
    }
    return ans;
}

int main() {
    int n;
    cin >> n;
    for(int i = 1;i <= n;i ++) {
        cin >> m[i] >> a[i];
    }
    cout << CRT(a,m,n) << endl;
    return 0;
}

2.中国剩余定理模板(EXCRT)/曹冲养猪

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;

const ll maxn = 1e7 + 5;

ll exgcd(ll a,ll b,ll &x,ll &y) {
    if(b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll r = exgcd(b,a % b,x,y);
    ll t = x;
    x = y;
    y = t - a / b * y;
    return r;
}

ll a[maxn],m[maxn];

ll exCRT(ll n) {
    ll M = m[1],A = a[1],x,y,d;
    for(ll i = 2;i <= n;i ++) {
        d = exgcd(M,m[i],x,y);
        if((A - a[i]) % d != 0) {
            return -1;
        }
        x = ((A - a[i]) / d * x % (m[i] / d) + m[i] / d) % (m[i] / d);
        A -= x * M;
        M = M / d * m[i];
        A = (A % M + M) % M;
    }
    return A;
}

int main() {
    ios::sync_with_stdio(false);
    ll n;
    cin >> n;
    for(ll i = 1;i <= n;i ++) {
        cin >> m[i] >> a[i];
    }
    cout << exCRT(n) << endl;
    return 0;
}

3.KMP字符串匹配

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 10000110;

int kmp[maxn];
char a[maxn],b[maxn];

int main() {
    cin >> a + 1;
    cin >> b + 1;
    int sza = strlen(a + 1),szb = strlen(b + 1);
    int j = 0;
    for(int i = 2;i <= szb;i ++) {
        while(j && b[i] != b[j + 1]) {
            j = kmp[j];
        }
        if(b[j + 1] == b[i]) {
            j ++;
        }
        kmp[i] = j;
    }
    j = 0;
    for(int i = 1;i <= sza;i ++) {
        while(j > 0 && b[j + 1] != a[i]) {
            j = kmp[j];
        }
        if(b[j + 1] == a[i]) {
            j ++;
        }
        if(j == szb) {
            cout << i - szb + 1 << endl;
            j = kmp[j];
        }
    }
    for(int i = 1;i <= szb;i ++) {
        cout << kmp[i] << " ";
    }
    return 0;
}

4.最小生成树算法

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 5e3 + 5;
const int maxm = 2e5 + 5;

struct Edge {
	int u,v;
	int len;
} E[maxm];

int father[maxn];

bool cmp(Edge a,Edge b) {
	return a.len < b.len;
}

void init(int n) {
	for(int i = 1;i <= n;i ++) {
		father[i] = i;
	}
}

int get_father(int x) {
	if(father[x] == x) {
		return x;
	}
	return father[x] = get_father(father[x]);
}

int kruskal(int n,int m) {
	int sum = 0;
	init(n);
	sort(E,E + m,cmp);
	for(int i = 0;i < m;i ++) {
		int fu = get_father(E[i].u);
		int fv = get_father(E[i].v);
		if(fu != fv) {
			father[fv] = fu;
			sum += E[i].len;
		}
	}
	return sum;
}

int main() {
	int n,m;
	cin >> n >> m;
	for(int i = 0;i < m;i ++) {
		cin >> E[i].u >> E[i].v >> E[i].len;
	}
	cout << kruskal(n,m) << endl;
	return 0;
}

5.康托展开

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 1e6 + 5;

int a[maxn];

long long fac[maxn];

bool vis[maxn];

int main() {
	int n;
	cin >> n;
	for(int i = 1;i <= n;i ++) {
		cin >> a[i];
	}
	fac[0] = 1;
	for(int i = 1;i <= n;i ++) {
		fac[i] = fac[i - 1] * i;
	}
	long long res = 0;
	memset(vis,0,sizeof(vis));
	for(int i = 1;i <= n;i ++) {
		int p = 0;
		for(int j = 1;j < a[i];j ++) {
			if(!vis[j]) {
				p ++;
			}
		}
		vis[a[i]] = true;
		res += fac[n - i] * p;
	}
	res ++;
	cout << res << endl;
	return 0;
}

6.单调栈

#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;

const int maxn = 3e7 + 5;

int a[maxn],f[maxn]; // a为输入数组,f为储存答案的数组 

stack<int> s;

int main() {
	ios::sync_with_stdio(false);
	int n;
	cin >> n;
	for(int i = 1;i <= n;i ++) {
		cin >> a[i];
	}
	for(int i = n;i >= 1;i --) {
		while(!s.empty() && a[s.top()] <= a[i]) {
			s.pop(); // 弹出栈顶比当前数小的 
		}
		if(s.empty() == false) {
			f[i] = s.top();
		} else {
			f[i] = 0;
		}
		// 储存答案,由于当前没有比它大的要输出0 
		s.push(i);
	}
	for(int i = 1;i <= n;i ++) {
		cout << f[i] << " ";
	}
	return 0;
}

7.裴蜀定理

#include <iostream>
#include <cstdio>
using namespace std;

int gcd(int a,int b) {
	if(b == 0) {
		return a;
	}
	return gcd(b,a % b);
}

int main() {
	int n;
	cin >> n;
	int ans;
	for(int i = 1;i <= n;i ++) {
		int x;
		cin >> x;
		if(x < 0) {
			x = -x;
		}
		if(i == 1) {
			ans = x;
		} else {
			ans = gcd(ans,x);
		}
	}
	cout << ans << endl;
	return 0;
}

8.卢卡斯定理/Lucas定理

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;

const int maxn = 1e7 + 5;

int n,m,p,l;

int fac[maxn],ifac[maxn];

int ksm(int x,int y) {
	int s = 1;
	for(register int i = y;i;i >>= 1,x = (ll)x * x % p ) {
		if(i & 1) {
			s = (ll)s * x % p;
		}
	}
	return s;
}

int lucas(int x,int y) {
	if(y > x) {
		return 0;
	}
	if(x == y) {
		return 1;
	}
	if(x > p || y > p) {
		return (ll)lucas(x / p,y / p) * lucas(x % p,y % p) % p;
	}
	return (ll)fac[x] * ifac[x - y] % p * ifac[y] % p;
}

int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while(t --) {
		cin >> n >> m >> p;
		fac[0] = 1;
		ifac[0] = 1;
		l = min(n + m,p - 1);
		for(register int i = 1;i <= l;i ++) {
			fac[i] = (ll)fac[i - 1] * i % p;
		}
		ifac[l] = ksm(fac[l],p - 2);
		for(register int i = l - 1;i;i --) {
			ifac[i] = (ll)ifac[i + 1] * (i + 1) % p;
		}
		cout << lucas(n + m,m) << endl;
	}
	return 0;
}

9.manacher算法求最长回文子串

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;

const int maxn = 1e7 + 5;

int n,m,p,l;

int fac[maxn],ifac[maxn];

int ksm(int x,int y) {
	int s = 1;
	for(register int i = y;i;i >>= 1,x = (ll)x * x % p ) {
		if(i & 1) {
			s = (ll)s * x % p;
		}
	}
	return s;
}

int lucas(int x,int y) {
	if(y > x) {
		return 0;
	}
	if(x == y) {
		return 1;
	}
	if(x > p || y > p) {
		return (ll)lucas(x / p,y / p) * lucas(x % p,y % p) % p;
	}
	return (ll)fac[x] * ifac[x - y] % p * ifac[y] % p;
}

int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while(t --) {
		cin >> n >> m >> p;
		fac[0] = 1;
		ifac[0] = 1;
		l = min(n + m,p - 1);
		for(register int i = 1;i <= l;i ++) {
			fac[i] = (ll)fac[i - 1] * i % p;
		}
		ifac[l] = ksm(fac[l],p - 2);
		for(register int i = l - 1;i;i --) {
			ifac[i] = (ll)ifac[i + 1] * (i + 1) % p;
		}
		cout << lucas(n + m,m) << endl;
	}
	return 0;
}

快速幂取模

。。。不知道为什么经常写错,所以在这里把它加上。

#include <iostream>
#include <cstdio>
using namespace std;

const int mod = 1e9 + 7;

int pow2(int x,int y) {
	int ans = 0;
	while(y) {
		if(y % 2 == 1) {
			ans = ans * x % mod;
		}
		x = x * x;
		y / = 2;
	}
	return ans % mod;
}

int main() {
	int n,m;
	cin >> n >> m;
	cout << pow2(n,m) << endl;
	return 0;
}