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