模板
1.素数筛法
const int N = 1e7+5;
const int mod = 1e9 + 7;
bool is_prime[N]={true,true};//将0,1筛去
int p[N];
int main()
{
int n;
cin>>n;
//筛法开始
for(int i=2;i*i<=n;i++)
{
if(!is_prime[i])
for(int j=i+i;j<=n;j+=i)
is_prime[j]=true;//筛去j的倍数
}
int k=1;
p[0]=2;
for(int i=3;i<=n;i+=2)//除去2 之外,没有偶的素数,可以只遍历奇素数
if(!is_prime[i])
p[k++]=i;//将素数按照顺序存入数组中
//结束
for(int i=0;i<k;i++)
printf("%d ",p[i]);
return 0;
}
2.欧拉筛
const int N = 1e7+5;
const int mod = 1e9 + 7;
bool is_prime[N]= {true,true}; //将0,1筛去,false表示素数
int p[N];//质数表
int main()
{
int n,k=0;
cin>>n;
//筛法开始
for(int i=2; i<=n; i++)
{
if(!is_prime[i])
p[k++]=i;
for(int j=0; p[j]*i<=n&&j<k; j++)
{
is_prime[i*p[j]]=true;
if(i%p[j]==0)
break;
}
}
for(int i=0; i<k; i++)
printf("%d ",p[i]);
return 0;
}
3.排序
#include <iostream>
#include <algorithm>
const int MAXN = (int)1e5 + 5;
int a[MAXN], n;
//冒泡排序
void bubble_sort() {
for (int i = n - 1; i > 0; --i) {
bool flag = false;
for (int j = 0; j + 1 <= i; ++j)
if (a[j] > a[j + 1]) {
std::swap(a[j], a[j + 1]);
flag = true;
}
if (!flag) return ;
}
return ;
}
//选择排序
void selection_sort() {
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if(a[i] > a[j])
swap(a[i], a[j]);
}
}
}
//插入排序
void insertion_sort() {
for (int i = 1; i < n; ++i) {
int t = a[i], j;
for (j = i - 1; j >= 0; --j) {
if (a[j] > t) {
a[j + 1] = a[j];
}
else
break;
}
a[j + 1] = t;
}
}
int b[MAXN];
//归并排序
/*
void merge_sort(int l, int r) {
if (l >= r) return ;
int mid = (l + r) >> 1;
merge_sort(l, mid);
merge_sort(mid + 1, r);
int i = l, j = mid + 1, cnt = 0;
while (i <= mid && j <= r)
if (a[i] <= a[j])
b[cnt++] = a[i++];
else
b[cnt++] = a[j++];
while (i <= mid) b[cnt++] = a[i++];
while (j <= r) b[cnt++] = a[j++];
for (int i = l, j = 0; j < cnt; ++i, ++j) a[i] = b[j];
}
*/
//归并排序求逆序对
int merge_sort(int l, int r) {
if (l >= r) return 0;
int mid = (l + r) >> 1, res = 0;
res += merge_sort(l, mid);
res += merge_sort(mid + 1, r);
int i = l, j = mid + 1, cnt = 0;
while (i <= mid && j <= r)
if (a[i] <= a[j])
b[cnt++] = a[i++];
else {
res += mid - i + 1;
b[cnt++] = a[j++];
}
while (i <= mid) b[cnt++] = a[i++];
while (j <= r) b[cnt++] = a[j++];
for (int i = l, j = 0; j < cnt; ++i, ++j) a[i] = b[j];
return res;
}
//快速排序
void quick_sort(int l, int r) {
if (l >=r ) return ;
int i = l - 1, j = r + 1, x = a[(l + r) >> 1];
while (i < j) {
do j--; while (a[j] > x);
do i++; while (a[i] < x);
if (i < j) std::swap(a[i], a[j]);
else quick_sort(l, j), quick_sort(j + 1, r);
}
}
int main() {
cin >> n;
for (int i = 0; i < n; ++i) cin >> a[i];
//bubble_sort();
//selection_sort();
// insertion_sort();
// cout << merge_sort(0, n - 1) << '\n';
// cout << bubble_sort() << '\n';
// quick_sort(0, n - 1);
for (int i = 0; i < n; ++i)
cout << a[i] << (i == n - 1 ? '\n' : ' ');
return 0;
}
//当然了,最常用的还是sort
4.快速幂取模
(积的取余等于取余的积的取余)
ll quick_pow(ll a,ll b,ll mod)//a是底数,b是指数,mod是取模
{
ll s=1;
a%=mod;
while(b>0)
{
if(b%2==1)
s=(s*a)%mod;
b/=2;
a=(a*a)%mod;
}
return s;
}
5.并查集
const int N = 1e5+5;
const int mod = 1e9 + 7;
int father[N];
void init()
{
for(int i=0;i<N;i++)
father[i]=i;
}
int findfather(int x)
{
if(father[x]==x)
return x;
else return father[x]=findfather(father[x]);
}
void Union(int x,int y)
{
int fx=findfather(x);
int fy=findfather(y);
if(fx!=fy)
father[x]=fy;
}
6.区间DP
for(int len=0;len<n;len++)
{
for(int i=1;i<=n-len;i++)
{
int j=i+len;
dp[i][j]=inf;
for(int k=i;k<=j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+…)
}
}
}
7.floyd算法
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
8.离散化处理
(1)
#include <iostream>
#include <bits/stdc++.h>
#define ll long long
//#define local
using namespace std;
const int N = 1e5+5;
const int inf = 0x3f3f3f3f;//1061109567
//离散化模板
int a[N],lsh[N],cnt;
int main()
{
#ifdef local
freopen("input.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
lsh[i]=a[i];
}
sort(lsh+1,lsh+n+1);
cnt=unique(lsh+1,lsh+n+1)-lsh-1;//去重
for(int i=1;i<=n;i++)
a[i]=lower_bound(lsh+1,lsh+cnt+1,a[i])-lsh;
return 0;
}
(2)
#include <iostream>
#include <bits/stdc++.h>
#define ll long long
//#define local
using namespace std;
const int N = 1e5+5;
const int inf = 0x3f3f3f3f;//1061109567
//离散化模板
struct node
{
int num,id;
}a[N];
int b[N];
bool cmp(node x,node y)
{
return x.num<y.num;
}
int main()
{
#ifdef local
freopen("input.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].num);
a[i].id = i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
b[a[i].id]=i;
return 0;
}
9. 二分
int binary (int n)
{
int l=1,r=n,ans=0;
while(l<=r)
{
int mid = (l+r)/2;
if(条件满足)
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
return ans;
}
10.单调栈——求以a[i]为最小(大)值的区间和
ll t,n,a[N],l[N],r[N];
ll fun()
{
for(ll i=1; i<=n; i++)
{
ll j=i;
while(j>1&&a[j-1]>=a[i])
j=l[j-1];
l[i]=j;
}
for(ll i=n; i>=1; i--)
{
ll k=i;
while(k<n&&a[k+1]>=a[i])
k = r[k+1];
r[i]=k;
}
ll num=0;
for(int i=1; i<=n; i++)
num+=a[i]*(r[i]-l[i]+1+(i-l[i])*(r[i]-i));
return num;
}
11. 堆的删除、插入
小根堆
int n,a[N],tol=0,ans=0;
void Insert(int x)
{
tol++;
a[tol]=x;
int i=tol,j=i/2;
while(j>0&&a[j]>a[i])
{
swap(a[j],a[i]);
i=j;
j=i/2;
}
}
int Pop()
{
int x=a[1];
a[1]=a[tol];
tol--;
int i=1,j=i*2;
if(j+1<=tol&&a[j+1]<a[j])
j++;
while(j<=tol && a[j]<a[i])
{
swap(a[j],a[i]);
i = j;
j = i*2;
if(j+1<=tol&&a[j+1]<a[j])
j++;
}
return x;
}
12.KMP
void p_tab(string pat,int pref[],int n)
{
pref[0]=0;
int len=0,i=1;
while(i<n)
{
if(pat[i]==pat[len])
{
len++;
pref[i]=len;
i++;
}
else
{
if(len>0)
len=pref[len-1];
else
pref[i]=len,i++;
}
}
for(int i=n-1; i>0; i--)
pref[i]=pref[i-1];
pref[0]=-1;
}
void kmp(string text,string pat)
{
int m=text.size();
int n=pat.size();
int pref[n+5];
p_tab(pat,pref,n);
int i=0,j=0;
while(i<m)
{
if(j==n-1&&text[i]==pat[j])
{
printf("found at %d\n",i-j);
j=pref[j];
}
if(text[i]==pat[j])
i++,j++;
else
{
j=pref[j];
if(j==-1)
i++,j++;
}
}
}
13.求n!的尾数(最右边的非零数)
知识太难理解了,暂且记下代码。
int f[10]= {1,1,2,6,4,4,4,8,4,6};
int fun(int n)
{
if(n<5)
return f[n];
int t=f[n%10]*6%10;
for(int i=1,r=n/5%4;i<=r;i++){
if(t==2||t==6)
t+=10;
t/=2;
}
return fun(n/5)*t%10;
}
*至于求尾数0的个数,其实就是求5的个数。
void (int m)
{
int ans=0;
while(m)
{
ans+=m/5;
m/=5;
}
return ans;
}
14.dijkstra算法
int n,m,a,b;
struct Edge
{
int from,to,dis;
Edge(int u,int v,int d):from(u),to(v),dis(d) {}
};
vector<int> g[N];
vector<Edge> e;
bool done[N];
int d[N];
int p[N];
void init(int n)
{
for(int i=0; i<n; i++)
g[i].clear();
e.clear();
}
void AddEdge(int f,int t,int d)
{
e.push_back(Edge(f,t,d));
int s=e.size();
g[f].push_back(s-1);
}
struct node
{
int d,u;
bool operator <(const node &b) const
{
return d>b.d;
}
};
void dijkstra(int s)
{
priority_queue<node> q;
for(int i=0;i<n;i++) d[i]=inf;
d[s]=0;
memset(done,0,sizeof done);
q.push((node){0,s});
while(!q.empty())
{
node x=q.top();q.pop();
int u=x.u;
if(done[u]) continue;
done[u]=1;
for(int i=0;i<g[u].size();i++)
{
Edge& E=e[g[u][i]];
if(d[E.to]>d[u]+E.dis)
{
d[E.to]=d[u]+E.dis;
p[E.to]=g[u][i];
q.push((node){d[E.to],E.to});
}
}
}
}