CSP-S可能出现的模板(非原创,各个地方整理得)
CSP-S rp+++++++++++
数学
快速幂
int pw(int a,int b){
int res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
Lucas(附赠线性求逆元)
int ny[N],jc[N],jcny[N];
void init(){
ny[1]=1;
for(int i=2;i<N;i++) ny[i]=(mod-mod/i)*ny[mod%i]%mod;
jcny[0]=jcny[1]=1;
for(int i=2;i<N;i++) jcny[i]=jcny[i-1]*ny[i]%mod;
jc[0]=jc[1]=1;
for(int i=2;i<N;i++) jc[i]=jc[i-1]*i%mod;
}
int c(int a,int b){
if(b>a) return 0;
return jc[a]*jcny[a-b]%mod*jcny[b]%mod;
}
int lucas(int a,int b){
if(!b) return 1;
return c(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
exgcd
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
exgcd求逆元
ll inv(ll a, ll m){
ll x, y;
ll d = exgcd(a, m, x, y);
return d == 1 ? (x + m) % m : -1;
}
费马小定理求逆元
ll inv(ll a, ll p) { return Pow(a, p - 2, p); }
线性求逆元
for (int i = 2; i < n; i++) inv[i] = inv[p % i] * (p - p / i) % p;
线性同余方程(删除原因:没有仔细阅读 这是拓展大步小步)
ll exbsgs(ll a, ll b, ll p){
if (b == 1LL) return 0;
ll t, d = 1, k = 0;
while ((t = gcd(a, p)) != 1){
if (b % t) return -1;
++k, b /= t, p /= t, d = d * (a / t) % p;
if (b == d) return k;
}
map<ll, ll> dic;
ll m = ceil(sqrt(p));
ll a_m = Pow(a, m, p), mul = b;
for (ll j = 1; j <= m; ++j) mul = mul * a % p, dic[mul] = j;
for (ll i = 1; i <= m; ++i){
d = d * a_m % p;
if (dic[d]) return i * m - dic[d] + k;
}
return -1;
}
CRT
LL CRT(int k, LL* a, LL* r) {
LL n = 1, ans = 0;
for (int i = 1; i <= k; i++) n = n * r[i];
for (int i = 1; i <= k; i++) {
LL m = n / r[i], b, y;
exgcd(m, r[i], b, y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}
exCRT
ll excrt(){
M=b[1];
ans=a[1];
for(ll i=2;i<=n;++i){
ll c=((a[i]-ans)%b[i]+b[i])%b[i];
ll g=exgcd(M,b[i],x,y);
ll p=b[i]/g;
x=mul(x,c/g,p);
ans+=x*M;
M*=p;
ans=(ans%M+M)%M;
}
return ans;
}
欧拉筛
bool vis[N];
int p[N],phi[N],cnt=1;
void initphi(){
phi[1]=1;
for(int i=2;i<N;i++){
if(!vis[i]){
p[cnt++]=i;
phi[i]=i-1;
}
for(int j=1;j<cnt&&i*p[j]<N;j++){
vis[i*p[j]]=1;
if(i%p[j]==0){
phi[i*p[j]]=phi[i]*p[j];
break;
}
else phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
}
Miller Rabin
bool Miller_Rabin(ll n, int s){
if (n == 2) return 1;
if (n < 2 || !(n & 1)) return 0;
int t = 0;
ll x, y, u = n - 1;
while ((u & 1) == 0) t++, u >>= 1;
for (int i = 0; i < s; i++){
ll a = rand() % (n - 1) + 1;
ll x = Pow(a, u, n);
for (int j = 0; j < t; j++){
ll y = Mul(x, x, n);
if (y == 1 && x != 1 && x != n - 1) return 0;
x = y;
}
if(x != 1) return 0;
}
return 1;
}
欧拉函数(单个)
ll euler(ll n){
ll rt = n;
for (int i = 2; i * i <= n; i++){
if (n % i == 0){
rt -= rt / i;
while (n % i == 0) n /= i;
}
}
if (n > 1) rt -= rt / n;
return rt;
}
除法分块
for(int l=1,r;l<=n;l=r+1){
r=(n/(n/l));
cout<<(n/l)<<' '<<(r-l+1)<<endl;
}
扫描线
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
const int MAXN = 1e6 + 10;
typedef long long ll;
int n, cnt = 0;
ll x1, y1, x2, y2, X[MAXN << 1];
struct ScanLine {
ll l, r, h;
int mark;
// mark用于保存权值 (1 / -1)
bool operator < (const ScanLine &rhs) const {
return h < rhs.h;
}
} line[MAXN << 1];
struct SegTree {
int l, r, sum;
ll len;
// sum: 被完全覆盖的次数;
// len: 区间内被截的长度。
} tree[MAXN << 2];
void build_tree(int x, int l, int r) {
// 我觉得最不容易写错的一种建树方法
tree[x].l = l, tree[x].r = r;
tree[x].len = 0;
tree[x].sum = 0;
if(l == r)
return;
int mid = (l + r) >> 1;
build_tree(lson, l, mid);
build_tree(rson, mid + 1, r);
return;
}
void pushup(int x) {
int l = tree[x].l, r = tree[x].r;
if(tree[x].sum /* 也就是说被覆盖过 */ )
tree[x].len = X[r + 1] - X[l];
// 更新长度
else
tree[x].len = tree[lson].len + tree[rson].len;
// 合并儿子信息
}
void edit_tree(int x, ll L, ll R, int c) {
int l = tree[x].l, r = tree[x].r;
// 注意,l、r和L、R的意义完全不同
// l、r表示这个节点管辖的下标范围
// 而L、R则表示需要修改的真实区间
if(X[r + 1] <= L || R <= X[l])
return;
// 这里加等号的原因:
// 假设现在考虑 [2,5], [5,8] 两条线段,要修改 [1,5] 区间的sum
// 很明显,虽然5在这个区间内,[5,8] 却并不是我们希望修改的线段
// 所以总结一下,就加上了等号
if(L <= X[l] && X[r + 1] <= R) {
tree[x].sum += c;
pushup(x);
return;
}
edit_tree(lson, L, R, c);
edit_tree(rson, L, R, c);
pushup(x);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%lli %lli %lli %lli", &x1, &y1, &x2, &y2);
X[2 * i - 1] = x1, X[2 * i] = x2;
line[2 * i - 1] = (ScanLine) {x1, x2, y1, 1};
line[2 * i] = (ScanLine) {x1, x2, y2, -1};
// 一条线段含两个端点,一个矩形的上下边都需要扫描线扫过
}
n <<= 1;
// 直接把 n <<= 1 方便操作
sort(line + 1, line + n + 1);
sort(X + 1, X + n + 1);
int tot = unique(X + 1, X + n + 1) - X - 1;
// 去重最简单的方法:使用unique!(在<algorithm>库中)
build_tree(1, 1, tot - 1);
// 为什么是 tot - 1 :
// 因为右端点的对应关系已经被篡改了嘛…
// [1, tot - 1]描述的就是[X[1], X[tot]]
ll ans = 0;
for(int i = 1; i < n /* 最后一条边是不用管的 */ ; i++) {
edit_tree(1, line[i].l, line[i].r, line[i].mark);
// 先把扫描线信息导入线段树
ans += tree[1].len * (line[i + 1].h - line[i].h);
// 然后统计面积
}
printf("%lli", ans);
return 0;
}
高斯消元
#include<bits/stdc++.h>
using namespace std;
const int N=1e2+5;
int n;
double a[N][N],eps=1e-6;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n+1;j++){
cin>>a[i][j];
}
}
int now=1;
for(int i=1;i<=n;i++){
int pos=now;
for(int j=now;j<=n;j++){
if(abs(a[j][i])>abs(a[pos][i])){
pos=j;
}
}
if(abs(a[pos][i])<eps){
continue;
}
swap(a[now],a[pos]);
for(int j=n+1;j>=i;j--){
a[now][j]/=a[now][i];
}
for(int j=now+1;j<=n;j++){
for(int k=n+1;k>=i;k--){
a[j][k]-=a[now][k]*a[j][i];
}
}
now++;
}
if(now<=n){
for(int i=now;i<=n;i++){
if(abs(a[i][n+1])>eps){
cout<<-1;
return 0;
}
}
cout<<0;
return 0;
}
for(int i=n;i>=1;i--){
for(int j=i+1;j<=n;j++){
a[i][n+1]-=a[i][j]*a[j][n+1];
}
}
for(int i=1;i<=n;i++){
cout<<"x"<<i<<"="<<a[i][n+1]<<'\n';
}
}
数据结构~
单调栈
void insert(int x){
while(!sta.empty()&&sta.top()<x)sta.pop();
sta.push(x);
}
单调队列
deque<int>d;
for(int i=1;i<=n;i++){
cin>>a;
while(!d.empty()&&d.end()>a)d.pop_back();
d.push_back(a);
}
01trie~
int t[N*31][2],nv=1;
void build(int p,int d,int v){
bool flag=(v&(1<<d));
if(!t[p][flag]) t[p][flag]=++nv;
if(d) build(t[p][flag],d-1,v);
}
int query(int p,int d,int v){
if(d<0) return 0;
bool flag=(v&(1<<d));
if(t[p][!flag]) return (1<<d)+query(t[p][!flag],d-1,v);
if(t[p][flag]) return query(t[p][flag],d-1,v);
}
ST表
#include <bits/stdc++.h>
using namespace std;
const int logn = 21;
const int maxn = 2000001;
int f[maxn][logn + 1], Logn[maxn + 1];
int read() { // 快读
char c = getchar();
int x = 0, f = 1;
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;
}
void pre() { // 准备工作,初始化
Logn[1] = 0;
Logn[2] = 1;
for (int i = 3; i < maxn; i++) {
Logn[i] = Logn[i / 2] + 1;
}
}
int main() {
int n = read(), m = read();
for (int i = 1; i <= n; i++) f[i][0] = read();
pre();
for (int j = 1; j <= logn; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); // ST表具体实现
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
int s = Logn[y - x + 1];
printf("%d\n", max(f[x][s], f[y - (1 << s) + 1][s]));
}
return 0;
}
树状数组
#define lower_bit(x) (x)&-(x)
using namespace std;
int n,m,tree[200000+10];
void add(int a,int c){
for(int i=a;i<=n;i+=lower_bit(i))tree[i]+=c;
}
int find(int r){
int ret=0;
for(int i=r;i>=1;i-=lower_bit(i))ret+=tree[i];
return ret;
}
线段树~
void addtag(int iSeg,int val){
tr[iSeg].tag+=val;
tr[iSeg].sum+=(tr[iSeg].r-tr[iSeg].l+1)*val;
}
void pushup(int iSeg){
tr[iSeg].sum=tr[lsp].sum+tr[rsp].sum;
}
void pushdown(int iSeg){
addtag(lsp,tr[iSeg].tag);
addtag(rsp,tr[iSeg].tag);
tr[iSeg].tag=0;
}
void build(int iSeg,int l,int r){
tr[iSeg].l=l; tr[iSeg].r=r;
if(l==r){
tr[iSeg].sum=x[l];
tr[iSeg].tag=0;
return;
}
int mid=l+(r-l)/2;
build(lsp,l,mid); build(rsp,mid+1,r);
pushup(iSeg);
}
void modify(int iSeg,int l,int r,int val){
if(l<=tr[iSeg].l&&tr[iSeg].r<=r){
addtag(iSeg,val);
return;
}
pushdown(iSeg);
if(l<=tr[lsp].r)modify(lsp,l,r,val);
if(tr[rsp].l<=r)modify(rsp,l,r,val);
pushup(iSeg);
}
int query(int iSeg,int l,int r){
// cout<<iSeg<<" "<<l<<" "<<r<<" "<<tr[iSeg].l<<" "<<tr[iSeg].r<<endl;
if(l<=tr[iSeg].l&&tr[iSeg].r<=r) return tr[iSeg].sum;
pushdown(iSeg);
int sum=0;
if(l<=tr[lsp].r)sum+=query(lsp,l,r);
if(tr[rsp].l<=r)sum+=query(rsp,l,r);
return sum;
}
fhq treap~
mt19937 rnd(time(0));
const int Max_n=1e6+10;
class Node{
public:
int l_son=0,r_son=0;
int val,ind,size=0;
Node(){
l_son=r_son=size=0;
}
};
class treap{
public:
int size,root;
Node fhq[Max_n];
int new_node(int x){
fhq[++size].val=x;
fhq[size].ind=rnd();
fhq[size].l_son=fhq[size].r_son=0;
fhq[size].size=1;
return size;
}
treap(){
size=0,root=0;
}
void push_up(int x){
fhq[x].size=fhq[fhq[x].l_son].size+fhq[fhq[x].r_son].size+1;
}
void split(int x,int k,int &l,int &r){
if(!x){
l=r=0;
return;
}else if(fhq[x].val<=k){l=x;split(fhq[x].r_son,k,fhq[x].r_son,r);}
else{r=x;split(fhq[x].l_son,k,l,fhq[x].l_son);}
push_up(x);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(fhq[x].ind>fhq[y].ind){
fhq[x].r_son=merge(fhq[x].r_son,y);
push_up(x);
return x;
}else{
fhq[y].l_son=merge(x,fhq[y].l_son);
push_up(y);
return y;
}
}
void insert(int val){
int a,b=0;
split(root,val,a,b);
root=merge(merge(a,new_node(val)),b);
}
void del(int val){
int a,b,c=0;
split(root,val,a,b);
split(a,val-1,a,c);
c=merge(fhq[c].l_son,fhq[c].r_son);
root=merge(merge(a,c),b);
}
int get_rnk(int val){
int a,b;
split(root,val-1,a,b);
int ret=fhq[a].size;
root=merge(a,b);
return ret+1;
}
int get_num(int rnk){
int now=root;
while(now){
if(fhq[fhq[now].l_son].size+1==rnk)break;
else if(fhq[fhq[now].l_son].size+1>rnk)now=fhq[now].l_son;
else{
rnk-=fhq[fhq[now].l_son].size+1;
now=fhq[now].r_son;
}
}
return fhq[now].val;
}
int pre(int val){
int a,b=0;
split(root,val-1,a,b);
int now=a;
while(fhq[now].r_son)now=fhq[now].r_son;
int pr=fhq[now].val;
root=merge(a,b);
return pr;
}
int sub(int val){
int a,b=0;
split(root,val,a,b);
int now=b;
while(fhq[now].l_son)now=fhq[now].l_son;
int su=fhq[now].val;
root=merge(a,b);
return su;
}
};
除法分块
for(int l=1,r;l<=n;l=r+1){
r=(n/(n/l));
cout<<(n/l)<<' '<<(r-l+1)<<endl;
}
字符串
AC自动机(/KMP)
struct kkk{
int son[26],fail,flag,ans;
void clear(){memset(son,0,sizeof(son)),fail=flag=ans=0;}
}trie[maxn];
queue<int>q;
void insert(char* s,int num){
int u=1,len=strlen(s);
for(int i=0;i<len;i++){
int v=s[i]-'a';
if(!trie[u].son[v])trie[u].son[v]=++cnt;
u=trie[u].son[v];
}
if(!trie[u].flag)trie[u].flag=num;
Map[num]=trie[u].flag;
}
void getFail(){
for(int i=0;i<26;i++)trie[0].son[i]=1;
q.push(1);
while(!q.empty()){
int u=q.front();q.pop();
int Fail=trie[u].fail;
for(int i=0;i<26;i++){
int v=trie[u].son[i];
if(!v){trie[u].son[i]=trie[Fail].son[i];continue;}
trie[v].fail=trie[Fail].son[i]; in[trie[v].fail]++;
q.push(v);
}
}
}
void topu(){
for(int i=1;i<=cnt;i++)
if(in[i]==0)q.push(i);
while(!q.empty()){
int u=q.front();q.pop();vis[trie[u].flag]=trie[u].ans;
int v=trie[u].fail;in[v]--;
trie[v].ans+=trie[u].ans;
if(in[v]==0)q.push(v);
}
}
void query(char* s){
int u=1,len=strlen(s);
for(int i=0;i<len;i++)
u=trie[u].son[s[i]-'a'],trie[u].ans++;
}
字符串哈希
typedef unsigned long long ull;
const ull Seed_Pool[] = {146527, 19260817};
const ull Mod_Pool[] = {1000000009, 998244353};
struct Hash{
ull SEED, MOD;
vector<ull> p, h;
Hash() {}
Hash(const string& s, const int& seed_index, const int& mod_index){
SEED = Seed_Pool[seed_index];
MOD = Mod_Pool[mod_index];
int n = s.length();
p.resize(n + 1), h.resize(n + 1);
p[0] = 1;
for (int i = 1; i <= n; i++) p[i] = p[i - 1] * SEED % MOD;
for (int i = 1; i <= n; i++) h[i] = (h[i - 1] * SEED % MOD + s[i - 1]) % MOD;
}
ull get(int l, int r) { return (h[r] - h[l] * p[r - l] % MOD + MOD) % MOD; }
ull substr(int l, int m) { return get(l, l + m); }
};
图论
链式前向星
struct edge{int to,w,nxt;}e[M*2];
int hed[N],ecnt;
void add(int l,int r,int c){
e[++ecnt]=(edge){r,c,hed[l]};
hed[l]=ecnt;
}
dijkstra
struct edge{int to,w;};
vector<edge> e[N];
struct node{
int u,d;
bool operator<(const node&tmp)const{return d>tmp.d;}
};
priority_queue<node> q;
int dis[N];
bool vis[N];
void dijkstra(){
memset(dis,0x3f,sizeof dis);
q.push((node){s,0});
dis[s]=0;
while(!q.empty()){
int u=q.top().u;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=0;i<e[u].size();i++){
int v=e[u][i].to,cost=dis[u]+e[u][i].w;
if(dis[v]>cost){
dis[v]=cost;
q.push((node){v,cost});
}
}
}
}
熟练剖粪树链剖分+树链剖分LCA
void dfs(int u,int f){
size[u]=1;
for(int &v:V[u]){
if(v!=f){
fa[v]=u,deep[v]=deep[u]+1;dfs(v,u);size[u]+=size[v];
if(size[v]>=size[hson[u]])hson[u]=v,swap(v,V[u][0]);
}
}
}
void dfs2(int u,int f,int tp){
dfn[u]=cnt++,rnk[dfn[u]]=u,top[u]=tp;
for(int &v:V[u]){
if(v!=f){if(hson[u]==v)dfs2(v,u,tp);else dfs2(v,u,v);}
}
}
int LCA(int a,int b){
while(top[a]!=top[b]){
if(deep[top[b]]>deep[top[a]])swap(a,b);
a=fa[top[a]];
}
return deep[a]>deep[b]?b:a;
}
倍增LCA
void dfs(int root, int fno) {
fa[root][0] = fno;
dep[root] = dep[fa[root][0]] + 1;
for (int i = 1; i < 31; ++i) {
fa[root][i] = fa[fa[root][i - 1]][i - 1];
cost[root][i] = cost[fa[root][i - 1]][i - 1] + cost[root][i - 1];
}
int sz = v[root].size();
for (int i = 0; i < sz; ++i) {
if (v[root][i] == fno) continue;
cost[v[root][i]][0] = w[root][i];
dfs(v[root][i], root);
}
}
int lca(int x, int y) {
if (dep[x] > dep[y]) swap(x, y);
int tmp = dep[y] - dep[x], ans = 0;
for (int j = 0; tmp; ++j, tmp >>= 1)
if (tmp & 1) ans += cost[y][j], y = fa[y][j];
if (y == x) return ans;
for (int j = 30; j >= 0 && y != x; --j) {
if (fa[x][j] != fa[y][j]) {
ans += cost[x][j] + cost[y][j];
x = fa[x][j];
y = fa[y][j];
}
}
ans += cost[x][0] + cost[y][0];
return ans;
}
缩点tarjan
dfn[u]=low[u]=++cnt;vis[u]=1;
st.push(u);
for(auto v:V[u]){
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(vis[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
int p=0;scnt++;
do{
p=st.top(),vis[p]=0,scc[p]=scnt;
sc[scnt].push_back(p);
st.pop();
}while(p!=u);
}
}
拓扑排序
bool toposort() {
vector<int> L;
queue<int> S;
for (int i = 1; i <= n; i++)
if (in[i] == 0) S.push(i);
while (!S.empty()) {
int u = S.front();
S.pop();
L.push_back(u);
for (auto v : G[u]) {
if (--in[v] == 0) {
S.push(v);
}
}
}
if (L.size() == n) {
for (auto i : L) cout << i << ' ';
return true;
} else {
return false;
}
}
MST
for(int i=1;i<=n;i++)fa[i]=i;
while(!Q1.empty()){
auto [c,u,v]=Q1.top();Q1.pop();
if(find(u)==find(v))continue;
if(!(n--)||!(k--))break;
add(u,v);
ans=max(ans,c);
}
dinic
int n,m,s,t,u,v,dis[N],hed[N],rad[N];
struct edge{int to,w,nxt;}e[M*2];
int ecnt=1;
void add(int u,int v,int w){
e[++ecnt]=(edge){v,w,hed[u]};
hed[u]=ecnt;
}
void link(int u,int v,int w){
add(u,v,w);
add(v,u,0);
}
bool bfs(){
queue<int> q;
for(int i=s;i<=t;i++) dis[i]=-1;
dis[s]=0;
q.push(s);
while(!q.empty()){
int cur=q.front();
rad[cur]=hed[cur];
q.pop();
for(int i=hed[cur];i;i=e[i].nxt){
if(dis[e[i].to]==-1&&e[i].w){
dis[e[i].to]=dis[cur]+1;
q.push(e[i].to);
}
}
}
return dis[t]!=-1;
}
int dfs(int x,int flow){
if(x==t) return flow;
int cnt=0;
for(int i=rad[x];i&&flow;i=e[i].nxt){
rad[x]=i;
if(dis[e[i].to]==dis[x]+1&&e[i].w){
int ret=dfs(e[i].to,min(flow,e[i].w));
if(ret>0){
e[i].w-=ret;
e[i^1].w+=ret;
cnt+=ret;
flow-=ret;
}
}
}
return cnt;
}
MCMF
int n,m,s,t,dis[N],hed[N],rad[N],ans1,ans2;
bool vis[N];
struct edge{int to,w,c,nxt;}e[M*2];
int ecnt=1;
void add(int u,int v,int w,int c){
e[++ecnt]=(edge){v,w,c,hed[u]};
hed[u]=ecnt;
}
void link(int u,int v,int w,int c){
add(u,v,w,c);
add(v,u,0,-c);
}
#define TO e[i].to
#define COST dis[x]+e[i].c
bool spfa(){
for(int i=s;i<=t;i++) dis[i]=1e9;
for(int i=s;i<=t;i++) vis[i]=0;
queue<int> q;
q.push(s);
vis[s]=1,dis[s]=0;
while(!q.empty()){
int x=q.front();
rad[x]=hed[x];
q.pop();
vis[x]=0;
for(int i=hed[x];i;i=e[i].nxt)if(dis[TO]>COST&&e[i].w){
dis[TO]=COST;
if(!vis[TO]){
q.push(TO);
vis[TO]=1;
}
}
}
return dis[t]!=1e9;
}
int dfs(int x,int flow){
if(x==t) return flow;
vis[x]=1;
int cnt=0;
for(int i=rad[x];i&&flow;i=e[i].nxt){
rad[x]=i;
if(!vis[TO]&&dis[TO]==COST&&e[i].w){
int ret=dfs(TO,min(flow,e[i].w));
e[i].w-=ret;
e[i^1].w+=ret;
cnt+=ret;
flow-=ret;
ans2+=ret*e[i].c;
}
}
vis[x]=0;
return cnt;
}
其他
矩阵快速幂
typedef vector<ll> vec;
typedef vector<vec> mat;
mat mul(mat& A, mat& B){
mat C(A.size(), vec(B[0].size()));
for (int i = 0; i < A.size(); i++)
for (int k = 0; k < B.size(); k++)
if (A[i][k]) // 对稀疏矩阵的优化
for (int j = 0; j < B[0].size(); j++)
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
return C;
}
mat Pow(mat A, ll n){
mat B(A.size(), vec(A.size()));
for (int i = 0; i < A.size(); i++) B[i][i] = 1;
for (; n; n >>= 1, A = mul(A, A))
if (n & 1) B = mul(B, A);
return B;
}
本文作者:baoziawa
本文链接:https://www.cnblogs.com/baoziawa/p/18503304
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步