判断素数:
#include<iostream>
#include<math.h>
using namespace std;
bool su(int n){
int i=2;
if(n==1)
return false;
for(i=2;i<=sqrt(n);i++){
if(n%i==0)
break;
}
if(i>sqrt(n))
return true;
else
return false;
}
埃氏筛:
bool isnp[MAXN]; // is not prime: 不是素数
void init(int n)
{
for (int i = 2; i * i <= n; i++)
if (!isnp[i])
for (int j = i * i; j <= n; j += i)
isnp[j] = 1;
}
二分模板:
模板1:
while (l < r)
{
int mid = l + r >> 1; //(l+r)/2
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
模板2:
while (l < r)
{
int mid = l + r + 1 >> 1; //(l+r+1)/2
if (check(mid)) l = mid;
else r = mid - 1;
}
模板3:(浮点二分)
while(r-l>1e-5) //需要一个精度保证
{
double mid = (l+r)/2;
if(check(mid)) l=mid; //或r=mid;
else r=mid; //或l=mid;
}
并查集:
一般模板:
int Parent[MAXN];
//初始化,现在各自为王,自己就是一个集合
void init(int n){
for(int i=0;i<n;i++){
Parent[i]=i;
}
}
//查询根结点
int find(int x){
if(Parent[x]==x)
return x;
else{
Parent[x]=find(Parent[x]); //顺便把双亲结点也设置为根结点,路径压缩
return Parent[x];
}
}
//合并,把 j 合并到 i 中去,就是把j的双亲结点设为i
void merge(int i,int j){
Parent[find(j)] = find(i);
}
并查集按秩合并
//初始化
void init(int n){
for(int i=0;i<n;i++){
Parent[i]=i;
Rank[i]=1;
}
}
//合并
//合并
void merge(int i,int j){
int x = find(i),y = find(j); //分别找到结点i和结点j的根节点
if(Rank[x] < Rank[y]){ //如果以x作为根结点的子树深度小于以y作为根结点的子树的深度,则把x合并到y中
Parent[x]=y;
}
else{
Parent[y]=x;
}
if(Rank[x] == Rank[y] && x != y){ //如果深度相同且根结点不同,以x为根结点的子树深度+1
Rank[x]++;
}
}
//哈希表,搜索,优先队列
优先队列
struct node {
int x,y;
bool operator < (const node &b) const{
return this->x>b.x;//按x从小到大排列
//return this->x<b.x;//按x从大到小排列
}
};
priority_queue<node>que;
priority_queue<int,vector<int>,greater<int> > que1;//从小到大排列
priority_queue<int> que2;//默认从大到小排列
初始化
按照单元赋值,将一个区间的元素都赋同一个值
在头文件<algorithm>里面
例如int一维数组arr[MAX]:fill(arr, arr + n, 要填入的内容);
int二维数组arr[N][M]:fill(arr[0],arr[0]+N*M,要填入的内容);
vector<int>v1; fill(v1.begin(),v1.end(),2); fill(v1.begin(),v1.begin()+4,4);
memset(arr,0,sizeof(arr));//只能赋0或-1;
vector:
vector<int> v1;
vector<father> v2;
vector<string> v3;
vector<vector<int> >; //注意空格。这里相当于二维数组int a[n][n];
vector<int> v5 = { 1,2,3,4,5 }; //列表初始化,注意使用的是花括号
vector<string> v6 = { "hi","my","name","is","lee" };
vector<int> v7(5, -1); //初始化为-1,-1,-1,-1,-1。第一个参数是数目,第二个参数是要初始化的值
vector<string> v8(3, "hi");
vector<int> v9(10); //默认初始化为0
vector<int> v10(4); //默认初始化为空字符串
访问vector中的元素:
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << endl;
v1[i] = 100;//只能修改已存在的元素
cout << v1[i] << endl;
}
迭代器访问元素
vector<string> v6 = { "hi","my","name","is","lee" };
for (vector<string>::iterator iter = v6.begin(); iter != v6.end(); iter++)
{
cout << *iter << endl;
//下面两种方法都都可以检查迭代器是否为空
cout << (*iter).empty() << endl;
cout << iter->empty() << endl;
}
/*反向迭代器*/
for (vector<string>::reverse_iterator iter = v6.rbegin(); iter != v6.rend(); iter++)
{ cout << *iter << endl; }
最短路径
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXV =1000; //最大顶点数
const int INF = 100000000; //设INF为一个很大的数
int n, m, s, G[MAXV][MAXV]; //n为顶点数,m为边数,s为起点
int d[MAXV]; //起点到达各点的最短路径长度
bool vis[MAXV] = {false}; //标记数组,vis[i]==true表示已访问。初值均为false
void Dijkstra(int s) //s为起点
{
fill(d, d + MAXV, INF); //fill函数将整个d数组赋为INF
d[s] = 0; //起点s到达自身的距离为0
for(int i = 0; i < n; i++) //循环n次
{
int u = -1, MIN = INF; //u使得d[u]最小,MIN存放该最小的d[u]
for(int j = 0; j < n; j++) //找到未访问的顶点中d[]最小的
{
if(vis[j] == false && d[j] < MIN)
{
u = j;
MIN = d[j];
}
}
//找不到小于INF的d[u],说明剩下的顶点和起点s不连通
if(u == -1)
return;
vis[u] = true; //标记u为已访问
for(int v = 0; v < n; v++)
{
//如果v未访问 && u能到达v && 以u为中介点可以使d[v]更优
if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v])
{
d[v] = d[u] + G[u][v]; //优化d[v]
}
}
}
}
int main()
{
int u, v, w;
scanf("%d%d%d", &n, &m, &s); //顶点个数、边数、起点编号
fill(G[0], G[0] + MAXV * MAXV, INF); //初始化图G
for(int i = 0; i < m; i++)
{
scanf("%d%d%d", &u, &v, &w); //输入u,v以及u->v的边权
G[u][v] = w;
}
Dijkstra(s); //Dijkstra算法入口
for(int i = 0; i < n; i++)
{
printf("%d ", d[i]); //输出所有顶点的最短距离
}
return 0;
}
背包问题
01背包(每个物品只能选一次)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int v[MAXN]; // 体积
int w[MAXN]; // 价值
int f[MAXN][MAXN]; // f[i][j], j体积下前i个物品的最大价值
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> v[i] >> w[i];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
// 当前背包容量装不进第i个物品,则价值等于前i-1个物品
if(j < v[i])
f[i][j] = f[i - 1][j];
// 能装,需进行决策是否选择第i个物品
else
f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
}
/* 优化for(int i = 1; i <= n; i++)
{
for(int j = m; j >= v[i]; j--)
f[j] = max(f[j], f[j - v[i]] + w[i]);
} */
cout << f[n][m] << endl;
return 0;
}
/*优化
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int f[MAXN]; //
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++) {
int v, w;
cin >> v >> w; // 边输入边处理
for(int j = m; j >= v; j--)
f[j] = max(f[j], f[j - v] + w);
}
cout << f[m] << endl;
return 0;
}
*/
完全背包(每个物品可以选无限次)
#include<iostream>
using namespace std;
const int N = 1010;
int f[N];
int v[N],w[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i = 1 ; i <= n ;i ++)
{
cin>>v[i]>>w[i];
}
/*
优化前
for(int i = 1 ; i <= n ; i++)
for(int j = 0 ; j <= m ; j ++)
{
f[i][j] = f[i-1][j];
if(j-v[i]>=0)
f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
*/
for(int i = 1 ; i<=n ;i++)
for(int j = v[i] ; j<=m ;j++)
{
f[j] = max(f[j],f[j-v[i]]+w[i]);
}
cout<<f[m]<<endl;
}
多重背包
#include <bits/stdc++.h>
using namespace std;
int a[10005],b[10005],t=0,n,m,dp[10005]={ },w,v,s;
int main()
{
cin>>n>>m;//物品种数和背包容积
while(n--)
{
cin>>v>>w>>s;//第i种物品的体积和价值
while(s--)
{
a[++t]=v;
b[t]=w;
}//死拆,把多重背包拆成01背包
}
for(int i=1;i<=t;i++)
for(int j=m;j>=a[i];j--)
dp[j]=max(dp[j-a[i]]+b[i],dp[j]);//直接套01背包的板子
cout<<dp[m]<<endl;
return 0;
}
前缀和
在一个n*m的只包含 0 和 1 的矩阵里找出一个不包含0的最大正方形,输出边长。
输入文件第一行为两个整数n,m,接下来n 行,每行 m个数字,用空格隔开,$0$ 或 $1$。
一个整数,最大正方形的边长。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,m,a[101][101]={0};
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];}}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];}}
int ans=1,l=2;
while(l<=min(n,m)){
for(int i=l;i<=n;i++){
for(int j=l;j<=m;j++){
if(a[i][j]-a[i-l][j]-a[i][j-l]+a[i-l][j-l]==l*l)
ans=max(ans,l);}}
l++;
}
cout<<ans;
return 0;
}
差分
//要令某一段数组增加,假设要令从m到n增加x,则先求出差分数组c[max],令c[m]+=x,令c[n+1]-=x,之后再求前缀和
标签:int,mid,笔记,++,vector,MAXN,include
From: https://www.cnblogs.com/muqi2021/p/17431604.html