模板整理

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});
           }
       }
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值