模板整合
快读:
inline int read() { int i = 0, j = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')j = -1; ch = getchar(); } while (ch >= '0'&&ch <= '9') i = i * 10 + ch - '0', ch = getchar(); return i*j; }
快排:
#include <iostream>
#include<algorithm>
using namespace std;
int n, t, a[100010];
void qsort(int l, int r)
{
int i = l, j = r;
int mid = a[(l + r) >> 1];//基准数
while (i <= j) {
while (a[i] < mid)
i++;
while (a[j] > mid)
j--;
if (i <= j) {
swap(a[i], a[j]);
i++; j--;
}
}
if (l < j)qsort(l, j);//递归左边
if (r > i)qsort(i, r);//递归右边
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a, a+n);
for (int i = 0; i < n; i++)
cout << a[i] << " ";
return 0;
}
线性基:
#include<iostream> #include<algorithm> using namespace std; #define ll long long ll a[100010], b[70]; ll n, ans=0; int main() { cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i <n; i++) for (int j = 62; j >= 0; j--) if (1ll << j & a[i]) if (!b[j]) { b[j] = a[i]; break; } else a[i] ^= b[j]; for (int i = 62; i >= 0; i--) ans = max(ans, ans^b[i]); cout << ans << endl; return 0; } //c++ max函数头文件是#include<algorithm>
DFS:
int dx[] = { 0,1,0,-1 }; int dy[] = { 1,0,-1,0 }; void dfs()//参数用来表示状态 { if (到达终点状态) { ...//根据题意来添加 return; } if (越界或者是不符合法状态) return; for (扩展方式)//一般是四个方向扩展 { if (扩展方式所达到状态合法) { ....//根据题意来添加 标记; dfs(); 修改(剪枝); (还原标记); //是否还原标记根据题意 //如果加上(还原标记)就是 回溯法 } } }
二分:
No.1:最大的小值 1~9中最小的大于5的数
int erf(int le, int ri) {//求满足条件的最大值 while (le + 1 <ri) {//防止死循环 int mid = le + ri >> 1;// '+'优先级大于'>>' if (check(mid))//check()函数:mid满足条件 le = mid; else ri = mid; } return le; }
No.2:最小的大值 1~9中最大的小于5的数
int erf(int le, int ri) {//求满足条件的最小值 while (le + 1 <ri) {//防止死循环 int mid = le + ri >> 1;// '+'优先级大于'>>' if (check(mid))//check()函数:mid满足条件 ri = mid; else le = mid; } return ri; }
快速幂:
#include<iostream> #include<algorithm> using namespace std; #define ll long long int qmi(ll a, ll b, ll mod) { //求 a^b%p,时间复杂度 O(logn) ll flag = 1; while (b) { if (b & 1)flag = (flag*a)%mod; a = (a*a) % mod; b = b >> 1; } return flag%mod; } int qji(ll a, ll b, ll mod) { //求 a*b%p,时间复杂度 O(logn) ll flag = 0; while (b) { if (b & 1)flag = (flag + a) % mod; a = (a << 1) % mod; b = b >> 1; } return flag%mod; } int main() { ll a, b, c; cin >> a >> b >> c; cout << a << "^" << b << " mod " << c << "=" << qmi(a, b, c) << "\n"; cout << a << "*" << b << " mod " << c << "=" << qji(a, b, c) << "\n"; return 0; }
线性筛:
#include<iostream> #include<algorithm> #include <cstring> #include<vector> #include<math.h> using namespace std; int su[10000010];//素数表,默认为0,值为0代表是素数,值为1代表不是素数 bool out[10000010];//判断素数,默认为false 如果值为true,代表这个数不是质数 void aishai(int mm) { //埃式筛法 用时: 3761ms / 内存: 41580KB 一个测试点999ms su[0] = su[1] = 1; for (int i = 2; i <= sqrt(mm); i++) { if (su[i])continue; for (int j = i << 1; j <= mm; j += i) su[j] = 1; } } void olshai(int mm) //欧拉筛法 用时: 1654ms / 内存: 18052KB { vector<int>cun; //储存素数 out[0]=out[1] = 1; //0和1不是质数 没有,错一个测试点 for (int i = 2; i <= mm; i++) { if (!out[i])cun.push_back(i); //没被筛过,肯定是素数 int len = cun.size(); for (int j = 0; j < len&&i*cun[j] <= mm; j++) { //<=mm 没有等于的话,错两个测试点 out[i*cun[j]] = true; //素数的倍数肯定不是素数 if (i%cun[j] == 0)break; //主要优化点,如果i是素数的倍数的话,就结束 } } return; } bool issu(int a) { //最快判断素数 用时: 842ms / 内存: 780KB if (a == 0 || a == 1)return 0; if (a == 2 || a == 3)return 1; if (a % 6 != 1 && a % 6 != 5) return 0; int qa = sqrt(a); for (int i = 5; i <= qa; i++) if (a%i == 0 || a % (i + 1) == 0)return 0; return 1; } int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int n, m,t; cin >> n>>m; //aishai(n); for (int i = 0; i < m; i++) { cin >> t; if (!issu(t)) cout << "No\n"; else cout << "Yes\n"; } return 0; }
费马小定理:
/* 费马小定理: 假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p) 两边都mod p; 即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。 延伸:1. n*a^(p-1) ≡ n (mod p) 2. a^(p-2) ≡ a^(-1)(mod p) 正序逆序要灵活运用! (A/B)%mod => A%mod/B => n/B => n*B^(-1) => 延伸2 => n*(B^(mod-2))%mod */ #include<iostream> #include<algorithm> using namespace std; #define ll long long int qmi(ll a, ll b, ll mod) { //快速幂 ll flag = 1; while (b) { if (b & 1)flag = (flag*a) % mod; a = (a*a) % mod; b = b >> 1; } return flag%mod; } int main() { int t, n, b,mod=10007; cin >> t; while (t--) { cin >> n >> b; cout << n*qmi(b, mod-2, mod) % mod << "\n"; } return 0; }
KMP:
#include<iostream> #include<string> #include<stdio.h> using namespace std; const int maxn = 1e6; string tex, pat; //tex文本串 pat模式串 int nex[maxn]; void getnext(string pat, int lenpat) { //获取nex数组 int j = nex[0] = -1; //j相当于记录nex[i]的值 for (int i = 1; i < lenpat; i++) { //求next[1]~next[len-1] while (j != -1 && pat[i] != pat[j + 1]) { j = nex[j]; //j回退,直到j回退到-1或pat[i]==pat[j+1] } if (pat[i] == pat[j+1])j++; //相等,先令j指向这个位置。 nex[i] = j; //赋值给nex[i] } } int kmp(string tex, string pat) { int lent = tex.size(), lenp = pat.size(); getnext(pat,lenp); //获取模式串的nex[]数组 int cnt = 0, j = -1; //cnt:成功匹配次数 for (int i = 0; i < lent; i++) { //试图匹配tex // cout << "i= " << i << endl; while (j != -1 && tex[i] != pat[j + 1]) { j = nex[j]; //j回退,直到j回退到-1或pat[i]==pat[j+1] } if (tex[i] == pat[j + 1]) j++; //匹配的话,继续 if (j == lenp-1) cout << i+2-lenp<< "\n",cnt++, j = nex[j]; //i下标从零开始的,应该属输出 i+1-(lenp)+1 } return cnt; } int main() { cin >> tex>>pat; int lenp = pat.size(); kmp(tex, pat); for (int i = 0; i < lenp; i++) cout << nex[i]+1 << " "; return 0; }