复制代码

算法模板

gcd(最大公约数)

int gcd(int a,int b)
{
    if(b == 0)  return a;
    return gcd(b,a%b);
}

快速幂

ll ksm(ll a,ll b,ll p)
{
    ll ans = 1;
    while(b > 0)
   {
      if(b&1) ans = ans * a % p;
      a = a* a % p;
      b>>=1;
   }
    return ans;
}


exgcd(扩展欧几里得)

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

线性筛素数

for(int i=2;i<=n;i++)
{
    if(not_prime[i] == 0) plist[++cnt] = i;
    for(int j=1;j<=cnt;j++)
    {
        int x;
        x = i * plist[j];
        if(x > n) break;
        not_prime[x] = 1;
        if(i % plist[j] == 0) break;
    }
}

中国剩余定理(大数翻倍法)

ll merge(ll &a1,ll &m1,ll a2,ll m2)
{
   if(m2 > m1) swap(a1,a2),swap(m1,m2);
   while(a1 % m2 != a2) a1 += m1;
   m1 = lcm(m1,m2);
}

lucas定理

// f[] 为阶乘对p取模
ll c(ll a,ll b,ll p) // c(a,b)%p
{
   if(a < b) return 0;
   return f[a]*ksm(f[b],p-2,p)%p*ksm(f[a-b],p-2,p)%p; // 费马小定理
}
ll lucas(ll a,ll b,ll p)
{
   if(a < p && b < p) return c(a,b,p);
   return c(a%p,b%p,p)*lucas(a/p,b/p,p)%p;
}

快读

inline int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

Kruskal (最小生成树)

int father[N];
bool cmp(node a,node b)
{
	return a.w < b.w;
}
int find(int x)
{
	if(father[x] != x) father[x] = find(father[x]);
	return father[x];
}
int ans,cnt;
int n,m;
int main()
{
	cin>>n>>m;
	
	for(int i = 1; i <= n; i++)
	father[i] = i;
	
	for(int i = 0; i < m ; i++)
	cin>>e[i].u>>e[i].v>>e[i].w;
	
	sort(e,e + m,cmp);
	for(int i = 0 ;i < m; i++)
	{
		int fau = find(e[i].u);
		int fav = find(e[i].v);
		if(fau != fav)// 两点不连通
		{
			father[fau] = fav;//建立联通关系
			ans += e[i].w;
			cnt++;//边数 = 点数 - 1 则图恰好连通
			if(cnt == n - 1) break;
		}
	}
}

SPFA(最短路)

int mapp[N];
bool vis[N];
queue<int> q;
void SPFA(int u)
{
    memset(mapp,0x3f,sizeof(mapp));
    memset(vis,0,sizeof(vis));
    mapp[u] = 0; vis[u] = true;
    q.push(u);
    while(!q.empty())
    {
       int x = q.front();
       vis[x] = false;
       q.pop();
       for(int i=head[x];i;i=e[i].next)
       {
           int y = e[i].to;
           if(mapp[y] > mapp[x] + e[i].dis)
           {
               mapp[y] = mapp[x] + e[i].dis;
               if(vis[y] == false)
               {
                  vis[y] = true;
                  q.push(y);
               }
           }
       }
    }
}

SPFA(双端队列优化)

int mapp[N];
bool vis[N];
deque<int> q;
void SPFA(int u)
{
    memset(mapp,0x3f,sizeof(mapp));
    memset(vis,0,sizeof(vis));
    mapp[u] = 0; vis[u] = true;
    q.push_back(u);
    while(!q.empty())
    {
       int x = q.front();
       vis[x] = false;
       q.pop_front();
       for(int i=head[x];i;i=e[i].next)
       {
           int y = e[i].to;
           if(mapp[y] > mapp[x] + e[i].dis)
           {
               mapp[y] = mapp[x] + e[i].dis;
               if(vis[y] == false)
               {
                  vis[y] = true;
                  if(!q.empty()&&mapp[y] < mapp[q.front()]) q.push_front(y);
                  else q.push_back(y);
               }
           }
       }
    }
}

Dijkstra(堆优化)

Dijkstra 算法是一种类似于贪心的算法,步骤如下:

1、当到一个时间点时,图上部分的点的最短距离已确定,部分点的最短距离未确定。

2、选一个所有未确定点中离源点最近的点,把他认为成最短距离。

3、再把这个点所有出边遍历一边,更新所有的点。

struct node{
    int dis;
    int pos;
    bool operator <(const node &x)const
    {
        return x.dis < dis;
    }
};
priority_queue<node> q;
void Dijkstra(int u)
{
     memset(mapp,0x3f,sizeof(mapp));
     memset(vis,0,sizeof(vis));
     mapp[u] = 0;
     q.push((node){0,u});
     while(!q.empty())
     {
         node p = q.top();
         q.pop();
         int x = p.pos;
         if(vis[x]) continue;
         vis[x] = 1;
         for(int i=head[x];i;i=e[i].next)
         {
            int y = e[i].to;
            if(mapp[y] > mapp[x] + e[i].dis)
            {
               mapp[y] = mapp[x] + e[i].dis;
               q.push((node){mapp[y],y});
            }
         }
     }
}

Tarjan

void tarjan(int u)
{
   low[u] = dfn[u] = ++t;
   vis[u] = true;
   q.push(u);
   for(int i=head[u];i;i=e[i].next)
   {
        int  v = e[i].to;
        if(dfn[v] == 0)
        {
             tarjan(v);
             low[u] = min(low[u],low[v]);
         }
        else if(vis[v] == true)
        {
            low[u] = min(low[u],dfn[v]);
        }
    }
    if(dfn[u] == low[u])
    {
         int w;
         sccnt++;
         do
         {
             w = q.top();
             q.pop();
             vis[w] = false;
             color[w] = sccnt;
             siz[sccnt]++;
          }while(u != w);
    }
}

find(并查集)

int find(int x)
{
    if(x != father[x])
    father[x] = find(father[x]);
    return father[x];
}

秦九韶公式

bool calc(ll x)
{
    ll sum = 0;
    for(ll i=n;i>=1;i--)
    sum = ((A[i]+sum)*x)%p;
    sum = (sum + A[0])%p;
    if(sum == 0) return true;////如果答案是0说明x值为该多项式的解
    else return false;
}
posted @ 2021-10-03 20:47  Elgina  阅读(39)  评论(0)    收藏  举报