0 杂
//ASCII码
数字-48
A=65
a=97
//字符串分割
//从下标0开始取n-1个字符
str = str.substr(0,n-1)
//二维vector的添加数据以及遍历
vector<vector<int>> v;
for(int i = 0;i < 2;i++)
{
vector<int> tmp;
for(int j = 0;j < 2;j++)
{
tmp.push_back(j);
}
v.push_back(tmp);
}
for(int i = 0;i < v.size(); i++)
{
for(int j = 0;j < v[i].size();j++)
{
cout<<v[i][j]<<" ";
}
cout<<endl;
}
//cin加速
#include < iostream>
int main()
{
std::ios::sync_with_stdio(false);//消除输入输出缓存
std::cin.tie(0);//解除cin与cout的绑定,加快速率。
}
1 手写组合
//dfs版
#include<bits/stdc++.h>
using namespace std;
int a[]={1,2,3,4,5,6,7,8,9,10};
int vis[10];
void dfs(int k) {
if (k == 3) {
for(int i=0;i<3;i++)
if(vis[i]) cout<<a[i];
cout<<"-";
}
else {
vis[k] = 0; //不选中第k个数
dfs(k + 1); //继续搜下一个数
vis[k] = 1; //选这个数
dfs(k + 1); //继续搜下一个数
}
}
int main() {
dfs(0); //从第一个数开始
return 0;
}
2 手写全排列
#include<algorithm>
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
int b[20];
bool marked[20];
//手写全排列
void dfs(int s,int t)
{
//若要打印n个数中任意m个数的全排列,改为s==m
if(s == t)
{
//若要打印n个数中任意m个数的全排列,改为i<m
for(int i = 0;i < t;i++)
{
cout<<b[i]<<" ";
}
cout<<"\n";
return;
}
for(int i = 0;i < t;i++)
{
if(!marked[i])
{
marked[i] = true;
//注意是b[s]
b[s] = a[i];
dfs(s+1,t);
marked[i] = false;
}
}
}
int main(void)
{
int n;
cin>>n;
dfs(0,n);
return 0;
}
//STL全排列函数
C++ STL:求“下一个”排列组合的函数next_permutation()。
返回值:如果没有下一个排列组合,返回false,否则返回true。每执行next_permutation()一次,会把新的排列放到原来的空间里。
注意,它排列的范围是[first, last),包括first,不包括last。
next_permutation()从当前的全排列开始,逐个输出更大的全排列,而不是输出所有的全排列。
3 kmp
1. 初始化next数组,令 j = next[0] = -1;
2. 让i在1 ~ len - 1范围遍历,对每个i执行3、4,以求解next[i];
3. 不断让j = next[j],直到j回退为-1,或是s[i] == s[j+1]成立。
4. 如果s[i] == s[j+1],则next[i] = j+1,否则next[i] = j。
void getNext(void getNext(string s,int len)
{
int j = -1;
next[0] = -1; //初始化j = next[0] = -1
for(int i = 0; i < len; i++) //求解next[1] ~ next[len - 1]
{
while(j != -1 && s[i] != s[j + 1])
{
j = next[j]; //反复令j = next[j]
} // 直到j回退到-1,或是s[i] = s[j + 1]
if(s[i] == s[j + 1]) //如果s[i] == s[j+1]
{
j = j+1; //则next[i] = j + 1,先令j指向这个位置
}
next[i] = j;
}
}
bool kmp(string text,string pattern)
{
int n = text.length();
int m = pattern.length();
getNext(pattern,m); //计算pattern的next数组
int j = -1; //初始化j为-1,表示当前还没有任意一位被匹配
for(int i = 0; i < n; i++) //试图匹配text[i]
{
while(j != -1 && text[i] != pattern[j + 1])
{
j = next[j]; //不断回退,直到j回到-1或text[i] == pattern[j+1]
}
if(text[i] == pattern[j + 1])
{
j++; //text[i]与pattern[j+1]匹配成功,令j加1
}
if(j == m - 1) //pattern完全匹配,说明pattern是text的子串
{
return true;
}
}
return false;
})
4 并查集
int c[maxn], N;
inline void init()
{
for(int i=0; i<=N; i++){
c[i] = i;
}
}
int Findset(int x)
{
int root = x;
while(c[root] != root)
root = c[root];
int idx;
while(c[x] != root){ /// 路径压缩
idx = c[x];
c[x] = root;
x = idx;
}
return root;
}
inline void Join(int a, int b)
{
int A = Findset(a);
int B = Findset(b);
if(A != B) c[A] = B;
}
5 快排
void quickSort(int left,int right)
{
if(left > right)
return;
int i = left;
int j = right;
int tmp = num[i];
while(i < j)
{
while(num[j] >= tmp && i != j)
j--;
while(num[i] <= tmp && i != j)
i++;
if(i < j)
swap(num[i],num[j]);
}
num[left] = num[i];
num[i] = tmp;
//注意是i-1,不是什么mid-1
quickSort(left,i - 1);
quickSort(i+1,right);
return;
}
6 归并
#include <iostream>
using namespace std;
void Merge(int a[],int s,int m, int e,int tmp[])
{
//将数组a的局部a[s,m]和a[m+1,e]合并到tmp,并保证tmp有序,然后再拷贝回a[s,m]
//归并操作时间复杂度:O(e-m+1),即O(n)
int pb = 0;
int p1 = s,p2 = m+1;
while( p1 <= m && p2 <= e)
{
if( a[p1] < a[p2])
tmp[pb++] = a[p1++];
else
tmp[pb++] = a[p2++];
}
while( p1 <= m)
tmp[pb++] = a[p1++];
while( p2 <= e)
tmp[pb++] = a[p2++];
//0 ~ e-s+1
for(int i = 0; i < e-s+1; ++i)
a[s+i] = tmp[i];
}
void MergeSort(int a[],int s,int e,int tmp[])
{
if( s < e)
{
int m = s + (e-s)/2;
//注意是m,不是m-1
MergeSort(a,s,m,tmp);
MergeSort(a,m+1,e,tmp);
Merge(a,s,m,e,tmp);
}
}
int a[10] = { 13,27,19,2,8,12,2,8,30,89};
int b[10];
int main()
{
int size = sizeof(a)/sizeof(int);
MergeSort(a,0,size-1,b);
for(int i = 0; i < size; ++i)
cout << a[i] << ",";
cout << endl;
return 0;
}
7 重载运算符
//定义在结构体内部
bool operator <(const person &t)const{
return t.a > a;
}
sort(p+1, p+1+n*2);
struct node{
int id;
//优先队列排序用
ll dis_n;
node(int a,ll b){
id = a;
dis_n = b;
}
bool operator <(const node &a)const{
return dis_n>a.dis_n;
}
};
8 二分
int BinarySearch(int a[],int size,int p)
{
int L = 0; //查找区间的左端点
int R = size - 1; //查找区间的右端点
//左闭右闭就是 <=
while( L <= R) //如果查找区间不为空就继续查找
{
int mid = L+(R-L)/2; //取查找区间正中元素的下标
if( p == a[mid] )
return mid;
else if( p > a[mid])
L = mid + 1; //设置新的查找区间的左端点
else
R = mid - 1; //设置新的查找区间的右端点
}
return -1;
} //复杂度O(log(n))
//后继
#include<bits/stdc++.h>
using namespace std;
int a[1000];
int bin_search(int *a, int n, int x){ //a[0]~a[n-1]是单调递增的
int left = 0, right = n; //注意:不是 n-1,此时是左闭右开的[0,n)
while (left < right) {
int mid = left + (right-left)/2; //int mid=(left+right)>>1;
if (a[mid] >= x) right = mid;
else left = mid + 1;
} //终止于left = right
return left;
}
int main(){
int n = 100;
for(int i=0;i<n;i++) a[i]=2*i+2; //赋值,数字2~200,偶数
int test = 55; //找55或55的后继
int pos = bin_search(a,n,test);
cout<<"test="<<a[pos];
}
//前驱
#include<bits/stdc++.h>
using namespace std;
int a[1000];
int bin_search2(int *a, int n, int x){ //a[0]~a[n-1]是单调递增的
int left = 0, right = n;
while (left < right) {
int mid = left + (right-left + 1)/2 ;
if (a[mid] <= x) left = mid;
else right = mid - 1;
} //终止于left = right
return left;
}
int main(){
int n = 100;
for(int i=0;i<n;i++) a[i]=2*i+2; //赋值,数字2~200,偶数
int test = 55; //找55或55的前驱
int pos = bin_search2(a,n,test);
cout<<"test="<<a[pos];
}
//精度控制
for(int j = 0; j < 100; j++) //控制精度在10^(-2)
{
double mid = left + (right - left)/2;
if(getY(mid)*getY(right) <= 0)
left = mid;
else
right = mid;
}
printf("%.2lf ",right);
//精度控制
const double eps = 1e-3;
while(right - left > eps)
{
double mid = left + (right - left)/2;
if(mid*mid*mid < num)
left = mid;
else
right = mid;
}
9 GCD
//辗转相除法
//最大公因数普通算法
int gcd(int m,int n)
{
int t,r;
if (m<n)//为了确保是大数除小数
{
t=m;
m=n;
n=t;
}
while((m%n)!=0)//辗转相除
{
r=m%n;
m=n;
n=r;
}
return n;
}
'''
考察gcd性质,根据更相减损术可以知道一个等式:gcd(a,b)=gcd(a,b-a) 当然这里的前提是a<=b;
所以gcd(a+k,b+k)=gcd(a+k,b-a) 这里的a和b都是已知的
我们可以设c=b-a 即c是已知的 所以想要使得a+k与c的最大公因子尽可能地大 因为最大最大能到达c
显然这个式子的最大gcd一定为 c ,我们只需要计算出a 最少需要增加多少可以成为 c 的倍数,这个增量即是答案k
'''
#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;
int main(){
LL a,b;
cin>>a>>b;
LL m = abs(a-b);
LL d = a%m;
LL k;
k = (d==0 ? 0 : m-d);
cout<<k<<endl;
}
10 质因数个数
typedef long long ll;
ll n;
ll drivePrime(ll num)
{
ll i,cnt = 0,k = num;
for(i = 2; i * i <= k; i++)
{
if(num % i == 0)
{
while(num%i == 0)
num /= i;
cnt++;
}
}
if(num > 1)
cnt++;
return cnt;
}
11 素数
//线性筛
int su[2050],cnt;
bool isPrime[2050];
void prime()
{
cnt = 0;
memset(isPrime,true,sizeof(isPrime));
isPrime[0] = isPrime[1] = false; //0,1不是素数
//i从2到maxn
for(int i = 2;i <= maxn;i++) // <=
{
if(isPrime[i]) //保存素数
su[cnt++] = i;
for(int j = 0;j < cnt && su[j]*i <= 2020;++j) // <=
//false
isPrime[su[j]*i] = false;
}
}
12 DFS、BFS
迷宫
#include<stdio.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct node{
int x;
int y;
string path = "";
};
char graph[31][51];
int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};
bool marked[31][51];
char k[4]={'D','L','R','U'};
queue<node> qu;
void bfs(int x,int y)
{
marked[x][y] = true;
node n;
n.x = x;
n.y = y;
qu.push(n);
while(!qu.empty())
{
node cur = qu.front();
qu.pop();
for(int i = 0;i < 4;i++)
{
node newn;
newn.x = cur.x + dir[i][0];
newn.y = cur.y + dir[i][1];
//cout<<dir[i][0]<<endl;
if(newn.x == 29 && newn.y == 49)
{
newn.path = cur.path + k[i];
cout<<newn.path;
return;
}
//cout<<graph[1][0]<<endl;
if(newn.x >= 0 && newn.x < 30 && newn.y >=0 && newn.y < 50 && graph[newn.x][newn.y] == '0' && !marked[newn.x][newn.y])
{
//cout<<i<<":"<<newn.x<<endl;
marked[newn.x][newn.y] = true;
newn.path =cur.path + k[i];
qu.push(newn);
}
}
}
}
int main(void)
{
for(int i = 0;i < 30;i++)
{
for(int j = 0;j < 50;j++)
{
scanf("%c",&graph[i][j]);
}
getchar();
}
bfs(0,0);
return 0;
}
跳蚱蜢
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct node
{
node() {}
node(string ss,int tt)
{
s = ss,t = tt;
}
string s;
int t;
};
queue<node> q;
map<string,bool> mp;
void bfs()
{
while(!q.empty())
{
node now = q.front();
q.pop();
string s = now.s;
int step = now.t;
if(s == "087654321")
{
cout<<step<<"\n";
break;
}
int idx;
for(int i = 0; i < 10; i++)
{
if(s[i] == '0')
{
idx = i;
break;
}
}
for(int j = idx - 2; j <= idx + 2; j++)
{
if(j == idx)
continue;
int cur = (j+9)%9;
string news = s;
char tmp = news[idx];
news[idx] = news[cur];
news[cur] = tmp;
if(!mp[news])
{
mp[news] = true;
q.push(node(news,step+1));
}
}
}
}
int main(void)
{
string s = "012345678";
q.push(node(s,0));
mp[s] = true;
bfs();
return 0;
}
七段码
#include<string>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
int mp[10][10];
map<string,bool> m;
int cnt;
bool marked[10];
int c[10];
void init()
{
//并查集初始化
for(int i = 0;i < 7;i++)
c[i] = i;
}
int findSet(int x)
{
int root = x;
while(c[root] != root)
root = c[root];
int idx;
while(c[x] != root)
{
idx = c[x];
c[x] = root;
x = idx;
}
return root;
}
void join(int a,int b)
{
int A = findSet(a);
int B = findSet(b);
if(A != B)
{
c[A] = B;
}
}
bool check()
{
init();
for(int i = 0;i < 7;i++)
{
for(int j = 0;j < 7;j++)
{
if(mp[i][j] == 1 && marked[i] && marked[j])
{
join(i,j);
}
}
}
int ct = 0;
for(int i = 0;i < 7;i++)
{
if(marked[i] && c[i] == i)
ct++;
}
if(ct == 1)
return true;
return false;
}
void dfs(int s)
{
if(s == 7)
{
if(check())
cnt++;
}
else
{
marked[s] = true;
dfs(s+1);
marked[s] = false;
dfs(s+1);
}
}
int main(void)
{
for(int i = 0;i < 10;i++)
{
int u,v;
cin>>u>>v;
mp[u][v] = mp[v][u] = 1;
}
dfs(0);
cout<<cnt;
return 0;
}
全球变暖(DFS判断连通块个数)
#include<stdio.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
bool marked[1010][1010];
char graph[1010][1010];
//上,左,下,右
int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};
int n;
//每块陆地有多少个小格
int ct1;
//统计与海水相邻的格子数,如果ct2!=ct1,则说明有格子不临海
int ct2;
void dfs(int x,int y)
{
if(graph[x][y] == '.')
return ;
// cout<<"x: "<<x<<" y: "<<y<<endl;
marked[x][y] = true;
ct1++;
bool flag = false;
for(int i = 0; i < 4; i++)
{
int x1 = x + dir[i][0];
int y1 = y + dir[i][1];
if(x1 < n && x1 >= 0 && y1 < n && y1 >= 0 && !marked[x1][y1])
{
if(graph[x1][y1] == '.' && !flag)
{
// cout<<"x: "<<x<<" y: "<<y<<" x1: "<<x1<<" y1: "<<y1<<endl;
ct2++;
flag = true;
}
dfs(x1,y1);
}
}
}
int main(void)
{
cin>>n;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
cin>>graph[i][j];
}
}
int cnt = 0;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(!marked[i][j] && graph[i][j] == '#')
{
ct1 = 0;
ct2 = 0;
dfs(i,j);
if(ct1 == ct2 && ct2 != 0)
cnt++;
// cout<<"ct1: "<<ct1<<" ct2: "<<ct2<<" cnt: "<<cnt<<endl;
}
}
}
cout<<cnt;
return 0;
}
12 最短路
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int total = 1e4+10;
const int inf = 0x3f3f3f3f;
struct node{
int id;
//优先队列排序用
ll dis_n;
node(int a,ll b){
id = a;
dis_n = b;
}
bool operator <(const node &a)const{
return dis_n>a.dis_n;
}
};
struct edge{
int u,v,w;
edge(int a,int b,int c){
u = a;
v = b;
w = c;
}
};
vector<edge> e[total];
//注意map和set判重时间复杂度为log,如果能开大数组判重优先开数组
map<int,bool> mp;
priority_queue<node> q;
long long dis[2030];
int lms(int a,int b)
{
return a/__gcd(a,b) * b;
}
void dij()
{
int s = 1;
dis[s] = 0;
q.push(node(1,0));
while(!q.empty())
{
node now = q.top();
q.pop();
if(mp[now.id])
continue;
mp[now.id] = true;
for(int i = 0;i < e[now.id].size();i++)
{
int v = e[now.id][i].v;
int w = e[now.id][i].w;
if(!mp[v] && dis[now.id] + w < dis[v])
{
dis[v] = dis[now.id] + w;
q.push(node(v,dis[v]));
}
}
}
}
int main(void)
{
int n;
cin>>n;
//注意初始化dis数组为inf
memset(dis,inf,sizeof(dis));
for(int i = 1;i <= n;i++)
{
for(int j = i+1;j <= n;j++)
{
if(j - i <= 21)
{
int w = lms(j,i);
e[i].push_back(edge(i,j,w));
e[j].push_back(edge(j,i,w));
}
}
}
dij();
cout<<dis[n];
return 0;
}
13 快速幂
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
typedef long long ll;
ll fastPow(ll a, ll n,ll mod)
{
ll ans = 1;
//重要,防止下面的ans*a越界
a %= mod;
while(n)
{
if(n&1)
{
ans = (ans * a) % mod;
}
a = a*a%mod;
n>>=1;
}
return ans;
}
int main(void)
{
ll b,p,k;
cin>>b>>p>>k;
cout<<fastPow(b,p,k);
return 0;
}