算法模板
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;
}

浙公网安备 33010602011771号