noip模板不完全名录

目录

  1. 图论部分
    1. spfa
    2. dijkstra
    3. floyd
    4. LCA
    5. 树上差分
    6. 最小生成树
    7. 拓扑排序
  2. 数学部分
    1. 逆元,费马小定理(附快速幂)
    2. 不定方程求解,exgcd
    3. 线性素数筛

图论

1.spfa

queue <int> q;
int d[100003];
bool v[100003];
void spfa(int s)
{
	q.push(s);
	for(int i=1;i<=n;i++)
		d[i]=MAX;
	d[s]=0;
	while(!q.empty())
	{
		int tmp=q.front();
		q.pop();
		v[tmp]=0;
		for(int i=h[tmp];i;i=e[i].nxt)
			if(d[tmp]+e[i].capa<d[e[i].too])
			{
				d[e[i].too]=d[tmp]+e[i].capa;
				if(!v[e[i].too])//注意要判定是否在队列内,不然就是Bellman-ford了
				{
					v[e[i].too]=1;
					q.push(e[i].too);
				}
			}
	}
}

2.dijkstra(堆优化)

struct node
{
    int u;
    long long v;//特别注意long long
};
bool operator < (node a,node b)
{
    return a.v>b.v;
}//重载小于号,为了将大根堆改为小根堆,小根堆反了!
priority_queue<node>  heap;//优先和堆之间有一个下划线
void dijkstra()
{
    for(int i=1;i<=n;i++)
        dist[i]=inf;
    dist[s]=0;
    heap.push((node) {s,0});
    node tmp;
    while(heap.empty()==0)
    {
        tmp=heap.top();
        heap.pop();
        if(tmp.dis>d[tmp.p]) continue;//只用在距离上有就可以
        for(int i=h[tmp.u];i;i=e[i].nxt)//往周围广搜
            if(dist[e[i].too]>dist[e[i].from]+e[i].capa)
            {
                dist[e[i].too]=dist[e[i].from]+e[i].capa;
                heap.push((node){e[i].too,dist[e[i].too]});//将改变距离的加入优先队列
            }
    }
}

3.floyd(现在有更先进的Johnson全源最短路了)

for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        d[i][j]=0x3fffffff;
for(int i=1;i<=n;i++)
    d[i][i]=0;//不要忘记预处理!!
for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
            if(d[j][k]<d[j][i]+d[i][k])//变量位置好像只要保证前后对应就可以了,内外层没有影响
            	d[j][k]=d[j][i]+d[i][k];

4.LCA

int fa[500005][22],dep[500005];

void dfs(int ff,int ss,int d)//处理fa数组的初始值和深度
{
    fa[ss][0]=ff;
    dep[ss]=d;
    for(int i=h[ss];i;i=e[i].nxt)
        if(e[i].too!=ff)
            dfs(ss,e[i].too,d+1);
}

void bz()//建立倍增,外层幂数内层点
{
    for(int i=1;i<=19;i++)
        for(int j=1;j<=n;j++)
            fa[j][i]=fa[fa[j][i-1]][i-1];
}

int lca(int xx,int yy)//深度定位置,倍增同深度,一同向上找祖先
{
    if(xx==yy) return xx;
    if(dep[xx]<dep[yy]) swap(xx,yy);//深度定位置
    for(int i=19;i>=0;i--)
        if(dep[xx]-dep[yy]>=(1<<i))
            xx=fa[xx][i];////倍增同深度
    if(xx==yy) return xx;
    for(int i=19;i>=0;i--)
        if(fa[xx][i]!=fa[yy][i])
        {
            xx=fa[xx][i];
            yy=fa[yy][i];
        }//一同向上找祖先
    return fa[xx][0];
}

5.树上差分

int sign[300005]
void put_sign()
{
    for(int i=1;i<=PATHNUM;i++)
    {
        sign[path_begin[i]]++;
        sign[path_end[i]]++;
        sign[lca(path_begin[i],path_end[i])]-=2;
    }
}

int updata(int p)//每个点上储存的是该点到父亲节点上的连线被经过多少次
{
   if(h[p]==0) return sign[p];
   for(int i=h[p];i;i=e[i].nxt)
    	sign[p]+=updata();
   return sign[p];
}

6.最小生成树(kruscal)

void build()
{
    for(int i=1;i<=n;i++)
		f[i]=i;
    sort(e+1,e+1+m,cmp);
	int cnt=0;bool flag=0;
	for(int i=1;i<=m;i++)
	{
		if(find(e[i].from)!=find(e[i].too))
		{
			cnt++;//考虑要不要再建图存下这条边
			merge(e[i].from,e[i].too);
		}
		if(cnt==n-1)
		{
			flag=1;
			return;	
		}
	}
}

7.拓扑排序

int a[10003];
queue <int> q;
void toposort()
{
	for(int i=1;i<=n;i++)
		if(!in[i])
			q.push(i),a[++a[0]]=i;
	while(!q.empty())
	{
		int tmp=q.front();
		q.pop();
		for(int i=h[tmp];i;i=e[i].nxt)
		{
			in[e[i].too]--;
			if(!in[e[i].too])
				q.push(e[i].too),a[++a[0]]=e[i].too;
		}
	}
}

数学

1.逆元 费马逆元

long long ksm(long long aa,long long bb)
{
    long long r=aa;long long ans=1;
    while(bb)
    {
        if((bb&1)==1)
            ans=(ans*r)%p;
        r=(r*r)%p;
        bb/=2;
    }
}

long long fmny()//费马逆元
{
    return ksm(x,p-2);
}

2.exgcd

int x,y;
int exgcd(int a,int b)
{
	if(b==0)
	{
		x=1;y=0;
		return a;
	}
	int g=exgcd(b,a%b);
	int tmp=x;
	x=y;
	y=tmp-a/b*y;
	return g;
}

int minn(int a,int b,int x,int y)
{
    int g=exgcd(a,b);
    if(x<0)
        while(x<0)
            x=x+b*g
    else
        while(x>0)
            x=x-b*g
        x=x+b*g;
}

附一段推导(由于本人太菜有些地方不会推,这里只有部分推导)

\(b=0\)时,\(ax+by=gcd(a,0)=a\) 则此时x=1,(y什么值都可以赋过去)

\(b!=0\)时,(此处\(a/b\)均为向下取整的意思)

\(ax+by=gcd(a,b)\)

\(=gcd(b,a\%b)\)

\(=bx_1+(a\%b)y_1\)

\(=bx_1+(a-(a/b)*b)y_1\)

\(=ay_1+b[ x_1+(a/b)y_1 ]\)

\(x=y_1\),\(y=x_1+(a/b)y_1\)为公式中的递归式

int g=gcd(b,a%b)就是\(ax+by=bx_1+(a\%b)y1\)中变过来的

3.线性素数筛

bool is_not_prime[10000003];
int prime[10000003]

void p()
{
   is_not_prime[1]=1;
   for(int i=2;i<=n;i++)
	{
		if(!is_not_prime[i])
			prime[++num]=i;
		for(int j=1;j<=num&&i*prime[j]<=n;j++)
		{
			is_not_prime[i*prime[j]]=1;
			if(!i%prime[j])
				break;//筛到前一个能mod后为0
		}
	} 
}
posted @ 2021-11-17 20:57  云云云玩家  阅读(47)  评论(0)    收藏  举报