杂项
FastIO
namespace IO{
static int len=0;
static char ibuf[(1<<21)+5],*iS,*iT,out[(1<<17)+1];
#define gc() (iS==iT?iT=(iS=ibuf)+fread(ibuf,1,1<<21,stdin),(iS==iT?EOF:*iS++):*iS++)
inline int read(){
int x=0,f=0;char c=gc();
for(;c<'0'||c>'9';c=gc()) f|=c=='-';
for(;c>='0'&&c<='9';c=gc()) x=x*10+(c^48);
return f?-x:x;
}
inline void flush(){fwrite(out,1,len,stdout);len=0;}
inline void pc(char ch){out[len++]=ch;if(len>=100000) flush();}
inline void write(int x){
static int st[20],top=0;
if(x<0) putchar('-'),x=-x;
do{st[++top]=x-x/10*10,x/=10;}while(x);
while(top) pc(st[top--]+'0');
pc('\n');
}
}
树哈希
// Problem: P5043 【模板】树同构([BJOI2015]树的同构)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5043
// Memory Limit: 250 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N=55;
vector<int>g[N][N];
int n[N],mx[N][N],id,m;
inline void add(int x,int y){if(x&&y) g[id][x].push_back(y);}
inline int get(int x,int fa){
int sum=1,t;mx[id][x]=0;
for(auto y:g[id][x])
if(y!=fa) t=get(y,x),mx[id][x]=max(mx[id][x],t),sum+=t;
mx[id][x]=max(n[id]-sum,mx[id][x]);
return sum;
}
mt19937 rng(time(0));
ull ans[N],C=(rng()<<32ull)+rng(),mask=(rng()<<32ull)+rng();
map<ull,int>mp;
inline ull calc(ull x){
x^=mask,x^=x<<13;
x^=x>>7,x^=x<<17;
x^=mask;
return x;
}
inline ull dp(int x,int fa){
ull res=C;
for(auto y:g[id][x])
if(y!=fa) res+=calc(dp(y,x));
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>m;
for(int i=1;i<=m;++i){
cin>>n[i],id=i;
for(int j=1,x;j<=n[i];++j)
cin>>x,add(x,j),add(j,x);
get(1,0);
for(int j=1;j<=n[i];++j)
if(mx[i][j]<=n[i]/2) ans[i]=max(ans[i],dp(j,0));
if(!mp[ans[i]]) mp[ans[i]]=i;
cout<<mp[ans[i]]<<endl;
}
}
最小表示法
#include <bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int s[N],n;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i) cin>>s[i],s[i+n]=s[i];
int i=1,j=2,k;
while(i<=n&&j<=n){
k=0;
while(k<n&&s[i+k]==s[j+k]) ++k;
if(k==n) break;
if(s[i+k]>s[j+k]) i=i+k+1;
else j=j+k+1;
if(i==j) ++i;
}
k=min(i,j);
for(int i=0;i<n;++i) cout<<s[k+i]<<' ';
return 0;
}
字符串
KMP
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char a[N],b[N];
int nxt[N],n,m;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>a+1>>b+1;
n=strlen(a+1),m=strlen(b+1);
for(int j=0,i=2;i<=m;++i){
while(j&&b[j+1]!=b[i]) j=nxt[j];
if(b[j+1]==b[i]) ++j;
nxt[i]=j;
}
for(int j=0,i=1;i<=n;++i){
while(j&&b[j+1]!=a[i]) j=nxt[j];
if(b[j+1]==a[i]) ++j;
if(j==m){
cout<<i-m+1<<endl;
j=nxt[j];
}
}
for(int i=1;i<=m;++i)
cout<<nxt[i]<<" ";
}
Z 函数
// Problem: P5410 【模板】扩展 KMP/exKMP(Z 函数)
// URL: https://www.luogu.com.cn/problem/P5410
// Memory Limit: 500 MB
// Time Limit: 1000 ms
// Author: Nityacke
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e7+5;
char a[N],b[N];
int z[N],n,m;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>(a+1)>>(b+1);
n=strlen(a+1),m=strlen(b+1);
ll ans=m+1;
for(int i=2,l=0,r=0;i<=m;++i){
z[i]=i>r?0:min(r-i+1,z[i-l+1]);
while(b[1+z[i]]==b[i+z[i]]) ++z[i];
if(i+z[i]-1>r) l=i,r=i+z[i]-1;
ans^=1ll*i*(z[i]+1);
}
cout<<ans<<endl,ans=0;
for(int i=1,l=0,r=0;i<=n;++i){
int p=i>r?0:min(z[i-l+1],r-i+1);
while(p<m&&b[1+p]==a[i+p]) ++p;
if(i+p-1>r) r=i+p-1,l=i;
ans^=1ll*i*(p+1);
}
cout<<ans<<endl;
}
失配树
// Problem: P5829 【模板】失配树
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5829
// Memory Limit: 512 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int n,nxt[N],m;
int top[N],sz[N],son[N],dep[N],f[N];
vector<int>g[N];
char s[N];
inline void add(int x,int y){g[x].push_back(y);}
void dfs(int x,int fa){
sz[x]=1,dep[x]=dep[f[x]=fa]+1;
for(auto y:g[x])
if(y!=fa){
dfs(y,x),sz[x]+=sz[y];
if(sz[son[x]]<sz[y]) son[x]=y;
}
}
void dfs1(int x,int tp){
top[x]=tp;
if(son[x]) dfs1(son[x],tp);
for(auto y:g[x])
if(y!=son[x]&&y!=f[x])dfs1(y,y);
}
inline int lca(int x,int y){
while(top[x]!=top[y])
if(dep[top[x]]>dep[top[y]]) x=f[top[x]];
else y=f[top[y]];
return dep[x]<dep[y]?x:y;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>s+1>>m,n=strlen(s+1);
for(int i=2,j=0;i<=n;++i){
while(j&&s[i]!=s[j+1]) j=nxt[j];
if(s[i]==s[j+1]) ++j;
nxt[i]=j,add(j,i),add(i,j);
}
for(int i=1;i<=n;++i)
if(!dep[i]) dfs(i,0),dfs1(i,i);
int x,y;
while(m--)
cin>>x>>y,cout<<lca(f[x],f[y])<<endl;
}
Manacher
// Problem: P3805 【模板】manacher
// URL: https://www.luogu.com.cn/problem/P3805
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// Author: Nityacke
#include<bits/stdc++.h>
using namespace std;
const int N=1.1e7+5;
char s[N],a[N<<1];
int p[N<<1],n,ans,len;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>(s+1),len=strlen(s+1);
for(int i=1;i<=len;++i) a[++n]='#',a[++n]=s[i];
a[++n]='#';
for(int i=1,c=0,r=0;i<=n;++i){
p[i]=i<=r?min(p[2*c-i],r-i+1):1;
while(p[i]<i&&i+p[i]<=n&&a[i+p[i]]==a[i-p[i]]) ++p[i];
if(i+p[i]-1>r) r=i+p[i]-1,c=i;
}
for(int i=1;i<=n;++i) ans=max(ans,p[i]-1);
cout<<ans<<endl;
}
AC 自动机
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,K=26;
int ch[N][K],link[N],tot;
int q[N],l=1,r,idx[N],val[N],n;
inline void ins(char *s,int id){
int p=0;
for(int i=0;s[i];++i){
int c=s[i]-'a';
if(!ch[p][c]) ch[p][c]=++tot;
p=ch[p][c];
}
idx[id]=p;
}
char st[N*10];
vector<int>g[N];
void build(){
for(int i=0;i<K;++i)
if(ch[0][i]) q[++r]=ch[0][i];
while(l<=r){
int x=q[l++];
for(int i=0;i<K;++i)
if(!ch[x][i]) ch[x][i]=ch[link[x]][i];
else link[ch[x][i]]=ch[link[x]][i],q[++r]=ch[x][i];
g[link[x]].push_back(x);
}
}
void query(char *s){
int p=0;
for(int i=0;s[i];++i)
++val[p=ch[p][s[i]-'a']];
}
void dfs(int x){
for(auto y:g[x])
dfs(y),val[x]+=val[y];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
cin>>st,ins(st,i);
build();
cin>>st;
query(st);
dfs(0);
for(int i=1;i<=n;++i)
cout<<val[idx[i]]<<endl;
}
后缀数组
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
inline int idx(char c){if(c<='9') return c-'0'+1;if(c<='Z') return c-'A'+11;return c-'a'+37;}
char s[N];
int n,a[N],fir[N],sec[N],t[N],sa[N],num=62;
//sa[i] 排名为i的后缀起始位置
//fir[i] 起始位置为i的后缀排名
//sec[i] 第二关键字排名为i的起始位置
//t[i] 桶
inline void sa_sort()
{
for(int i=1;i<=n;++i) ++t[fir[i]=a[i]];
for(int i=1;i<=num;++i) t[i]+=t[i-1];
for(int i=n;i;--i) sa[t[fir[i]]--]=i;
for(int k=1;k<n;k<<=1)
{
int cnt=0;
for(int i=n;i>n-k;--i) sec[++cnt]=i;
for(int i=1;i<=n;++i) if(sa[i]>k) sec[++cnt]=sa[i]-k;
for(int i=1;i<=num;++i) t[i]=0;
for(int i=1;i<=n;++i) ++t[fir[sec[i]]];
for(int i=1;i<=num;++i) t[i]+=t[i-1];
for(int i=n;i;--i) sa[t[fir[sec[i]]]--]=sec[i],sec[i]=0;//
swap(fir,sec);
fir[sa[1]]=1,cnt=1;
for(int i=2;i<=n;++i)
fir[sa[i]]=(sec[sa[i]]==sec[sa[i-1]]&&sec[sa[i]+k]==sec[sa[i-1]+k])?cnt:++cnt;
if(cnt==n) break;
num=cnt;
}
}
int main()
{
cin>>s+1,n=strlen(s+1);
for(int i=1;i<=n;++i) a[i]=idx(s[i]);
sa_sort();
for(int i=1;i<=n;++i) cout<<sa[i]<<" ";
}
后缀自动机
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5,K=26;
int ans;
namespace SAM{
int len[N],link[N],sz[N],ch[N][K];
int last,tot;
inline void init(){
for(int i=1;i<=tot;++i)
for(int j=0;j<K;++j) ch[i][j]=0;
last=tot=1;
}
inline void add(int c){
int p=last,np=last=++tot;
len[np]=len[p]+1,sz[np]=1;
for(;p&&!ch[p][c];p=link[p]) ch[p][c]=np;
if(!p) return link[np]=1,void();
int q=ch[p][c];
if(len[q]==len[p]+1) return link[np]=q,void();
int nq=++tot;
len[nq]=len[p]+1,link[nq]=link[q],link[q]=link[np]=nq;
for(int i=0;i<K;++i) ch[nq][i]=ch[q][i];
for(;p&&ch[p][c]==q;p=link[p]) ch[p][c]=nq;
}
inline void ins(char *st){for(int i=0;st[i];i++) add(st[i]-'a');}
vector<int>g[N];
inline void add(int x,int y){g[x].push_back(y);}
inline void build(){for(int i=2;i<=tot;++i) add(link[i],i);}
void dfs(int x){
for(auto y:g[x]) dfs(y),sz[x]+=sz[y];
if(sz[x]>1) ans=max(ans,sz[x]*len[x]);
}
}
char st[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie();cout.tie();
cin>>st;
SAM::init(),SAM::ins(st);
SAM::build(),SAM::dfs(1);
cout<<ans<<endl;
}
广义后缀自动机
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e6+5,K=26;
namespace SAM{
int tot=1,pos[N],link[N],len[N];
int ch[N][K];
int q[N],l=1,r;
inline int ins(int c,int p){
if(ch[p][c]){
int q=ch[p][c];
if(len[p]+1==len[q]) return q;
int nq=++tot;
len[nq]=len[p]+1,link[nq]=link[q],link[q]=nq;
for(int i=0;i<K;++i) ch[nq][i]=ch[q][i];
for(;p&&ch[p][c]==q;p=link[p]) ch[p][c]=nq;
return nq;
}
int np=++tot;
len[np]=len[p]+1;
for(;p&&!ch[p][c];p=link[p]) ch[p][c]=np;
if(!p) return link[np]=1,np;
int q=ch[p][c];
if(len[q]==len[p]+1) return link[np]=q,np;
int nq=++tot;
len[nq]=len[p]+1,link[nq]=link[q],link[q]=link[np]=nq;
for(int i=0;i<K;++i) ch[nq][i]=ch[q][i];
for(;p&&ch[p][c]==q;p=link[p]) ch[p][c]=nq;
return np;
}
inline void ins(char *st){
int lst=1;
for(int i=0;st[i];i++) lst=ins(st[i]-'a',lst);
}
inline ll calc(){
ll ans=0;
for(int i=2;i<=tot;i++) ans+=len[i]-len[link[i]];
return ans;
}
}
int n;
char st[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
cin>>st,SAM::ins(st);
cout<<SAM::calc()<<endl<<SAM::tot<<endl;
}
回文自动机
// Problem: P5496 【模板】回文自动机(PAM)
// URL: https://www.luogu.com.cn/problem/P5496
// Memory Limit: 256 MB
// Time Limit: 500000 ms
// Author: Nityacke
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,K=26;
char s[N];
int n,fail[N],len[N],trans[N];
int ch[N][K],num[N],tot=1,lst;
inline int getfail(int x,int pos){
while(pos-len[x]-1<=0||s[pos-len[x]-1]!=s[pos]) x=fail[x];
return x;
}
inline int gettrans(int x,int pos){
while(len[x]+2>len[tot]/2||s[pos-len[x]-1]!=s[pos]) x=fail[x];
return x;
}
inline void ins(int c,int pos){
int p=getfail(lst,pos);
if(!ch[p][c]){
len[++tot]=len[p]+2,fail[tot]=ch[getfail(fail[p],pos)][c];
num[tot]=num[fail[tot]]+1,ch[p][c]=tot;
if(len[tot]<=2) trans[tot]=fail[tot];
else trans[tot]=ch[gettrans(trans[p],pos)][c];
}
lst=ch[p][c];
}
int ans;
signed main(){
cin>>(s+1),n=strlen(s+1);
len[1]=-1,fail[0]=1;
for(int i=1;i<=n;++i){
if(i>1) s[i]=(s[i]-97+ans)%26+97;
ins(s[i]-'a',i);
cout<<(ans=num[lst])<<' ';
}
}
图论
单源最短路
// Problem: P4779 【模板】单源最短路径(标准版)
// URL: https://www.luogu.com.cn/problem/P4779
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
using namespace std;
const int N=2e5+5;
vector<pair<int,int> >g[N];
int n,m,d[N],vis[N];
priority_queue<pair<int,int> >q;
inline void add(int x,int y,int w){g[x].push_back(mp(y,w));}
inline void dijkstra(int S){
memset(d,0x3f,sizeof d);
d[S]=0,q.push(mp(0,S));
while(!q.empty()){
int x=q.top().sec;q.pop();
if(vis[x]++) continue;
for(auto y:g[x])
if(d[y.fir]>d[x]+y.sec)
d[y.fir]=d[x]+y.sec,q.push(mp(-d[y.fir],y.fir));
}
}
int S;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>S;
for(int u,v,w,i=1;i<=m;++i)
cin>>u>>v>>w,add(u,v,w);
dijkstra(S);
for(int i=1;i<=n;++i) cout<<d[i]<<" ";
}
欧拉路
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int st[N],stk[N],top,m,n;
vector<int>E[N];
int from[N],to[N];
void dfs(int x){
for(int &i=st[x];i<E[x].size();)
dfs(E[x][i++]);
stk[++top]=x;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int x,y,i=1;i<=m;++i)
cin>>x>>y,E[x].push_back(y),++from[y],++to[x];
int c1=0,c2=0,start=1;
for(int i=1;i<=n;++i)
sort(E[i].begin(),E[i].end());
for(int i=1;i<=n;++i)
if(abs(from[i]-to[i])>1) return cout<<"No"<<endl,0;
else if(from[i]==to[i]+1) ++c2;
else if(from[i]==to[i]-1) start=i,++c1;
if(c1!=c2||c1>1) return cout<<"No"<<endl,0;
dfs(start);
for(int i=top;i;--i) cout<<stk[i]<<" ";
}
缩点
// Problem: P3387 【模板】缩点
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3387
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int low[N],dfn[N],st[N],ins[N],top,idx;
int val[N],bl[N],scc,a[N];
vector<int>g[N],G[N];
inline void add(int x,int y){g[x].push_back(y);}
inline void Add(int x,int y){G[x].push_back(y);}
void tarjan(int x){
low[x]=dfn[x]=++idx,ins[x]=1,st[++top]=x;
for(auto y:g[x])
if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(ins[y]) low[x]=min(low[x],dfn[y]);
if(low[x]<dfn[x]) return;
++scc;
while(st[top+1]!=x)
bl[st[top]]=scc,val[scc]+=a[st[top]],ins[st[top--]]=0;
}
int vis[N];
int ans[N],res,n,m;
inline int dfs(int x){
int sum=0;
if(vis[x]) return ans[x];
for(auto y:G[x])
sum=max(sum,dfs(y));
vis[x]=1;
res=max(res,ans[x]=sum+val[x]);
return ans[x];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1,u,v;i<=m;++i)
cin>>u>>v,add(u,v);
for(int i=1;i<=n;++i)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;++i)
for(auto y:g[i])
if(bl[y]!=bl[i]) Add(bl[i],bl[y]);
for(int i=1;i<=scc;++i)
if(!vis[i]) dfs(i);
cout<<res<<endl;
}
割点
// Problem: P3387 【模板】缩点
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3387
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int low[N],dfn[N],idx;
vector<int>g[N];
int cut[N],rt,n,m;
inline void add(int x,int y){g[x].push_back(y);}
void tarjan(int x){
low[x]=dfn[x]=++idx;
int cnt=0;
for(auto y:g[x])
if(!dfn[y]){
tarjan(y),low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
if(cnt++||x!=rt) cut[x]=1;
}
}
else low[x]=min(low[x],dfn[y]);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1,u,v;i<=m;++i)
cin>>u>>v,add(u,v),add(v,u);
for(int i=1;i<=n;++i)
if(!dfn[i]) rt=i,tarjan(i);
int cnt=0;
for(int i=1;i<=n;++i)
cnt+=cut[i];
cout<<cnt<<endl;
for(int i=1;i<=n;++i)
if(cut[i]) cout<<i<<' ';
}
点双连通分量
#include<bits/stdc++.h>
const int N=5e6+5;
using namespace std;
int to[N],ne[N],head[N],tot=1,res;
inline void add(int x,int y){to[++tot]=y,ne[tot]=head[x],head[x]=tot;}
int low[N],dfn[N],t;
int n,m,cnt;
int top,st[N];
vector<int>s[N];
void tarjan(int x,int fa)
{
low[x]=dfn[x]=++t,st[++top]=x;
int flag=0;
for(int y,i=head[x];i;i=ne[i])
if(!dfn[y=to[i]])
{
flag=1,tarjan(y,i),low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
++cnt;
while(st[top+1]!=y) s[cnt].push_back(st[top--]);
s[cnt].push_back(x);
}
}
else if(y!=fa) low[x]=min(low[x],dfn[y]);
if(!flag&&!fa) return s[++cnt].push_back(x),void();
}
int d[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
int x,y;
for(int i=1;i<=m;++i) cin>>x>>y,add(x,y),add(y,x);
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i,0);
cout<<cnt<<endl;
for(int i=1;i<=cnt;++i)
{
cout<<s[i].size();
for(auto x:s[i]) cout<<" "<<x;
cout<<endl;
}
return 0;
}
边双连通分量
#include<bits/stdc++.h>
const int N=5e6+5;
using namespace std;
int to[N],ne[N],f[N],tot=1,res;
inline void add(int x,int y){to[++tot]=y,ne[tot]=f[x],f[x]=tot;}
int low[N],dfn[N],t;
int c[N],cnt;
int n,m,v[N];
int top,st[N];
vector<int>s[N];
void tarjan(int x,int ine){
low[x]=dfn[x]=++t;
st[++top]=x;
for(int y,i=f[x];i;i=ne[i]){
if(!dfn[y=to[i]]){
tarjan(y,i),low[x]=min(low[x],low[y]);
if(low[y]>dfn[x]) v[i]=v[i^1]=1;
}
else if(i!=(ine^1)) low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]){
++cnt;
while(st[top+1]!=x) s[cnt].push_back(st[top]),c[st[top--]]=cnt;
}
}
int d[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
int x,y;
for(int i=1;i<=m;++i) cin>>x>>y,add(x,y),add(y,x);
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i,0);
cout<<cnt<<endl;
for(int i=1;i<=cnt;++i){
cout<<s[i].size();
for(int j=0;j<s[i].size();++j) cout<<" "<<s[i][j];
cout<<endl;
}
return 0;
}
2-SAT
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int n,m;
vector<int>g[N];
int idx,dfn[N],bl[N],low[N],st[N],top,scc,vis[N];
inline void add(int x,int y){g[x].push_back(y);}
void tarjan(int x){
low[x]=dfn[x]=++idx,st[++top]=x,vis[x]=1;
for(auto y:g[x])
if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(vis[y]) low[x]=min(low[x],dfn[y]);
if(low[x]<dfn[x]) return;
++scc;
while(st[top+1]!=x) bl[st[top]]=scc,vis[st[top--]]=0;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1,a,b,c,d;i<=m;++i)
cin>>a>>b>>c>>d,add(a+(!b)*n,c+d*n),add(c+(!d)*n,a+b*n);
for(int i=1;i<=n*2;++i) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;++i)
if(bl[i]==bl[i+n]) return cout<<"IMPOSSIBLE"<<endl,0;
cout<<"POSSIBLE"<<endl;
for(int i=1;i<=n;++i)
cout<<(bl[i]>bl[i+n])<<" ";
}
广义圆方树
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int h1[N],h2[N],e[N],ne[N],to[N],tot=1,node;
int dfn[N],low[N],idx;
int sum[N],s[N],fa[N],fw[N];
int f[N][15],dep[N],dis[N];
int n,m,q,A,B;
/*
h1 原图
h2 圆方树
sum 所在环上的边权和
s 所在环的前缀和
fa 搜索树上的父亲
fw 搜索树上到父亲的权值
f,dep,dis 圆方树上的值
A,B x,y到达lca的前一个节点(防止lca为方点的情况)
*/
inline void add(int *h,int x,int y,int z){e[++tot]=z,ne[tot]=h[x],h[x]=tot,to[tot]=y;}
//对一个环建成树
void build(int x,int y,int z){
int stot=z;
//环上前缀和
for(int i=y;i!=x;i=fa[i]) s[i]=stot,stot+=fw[i];
s[x]=sum[x]=stot;
add(h2,x,++node,0);
for(int i=y;i!=x;i=fa[i])
//到达方点的父亲的距离为边权
sum[i]=stot,add(h2,node,i,min(s[i],stot-s[i]));
}
void tarjan(int x,int ine){
dfn[x]=low[x]=++tot;
for(int y,i=h1[x];i;i=ne[i])
if(!dfn[y=to[i]]){
fa[y]=x,fw[y]=e[i];
tarjan(y,i),low[x]=min(low[x],low[y]);
//不是环保留结构
if(low[y]>dfn[x]) add(h2,x,++node,e[i]),add(h2,node,y,0);//广义圆方树:圆点方点交错排列
//if(low[y]>dfn[x]) add(h2,x,y,e[i]); //圆方树
}
else if(i!=(ine^1)) low[x]=min(low[x],dfn[y]);
for(int i=h1[x],y;i;i=ne[i])
//有一个子节点通过环拓展到了这个子节点
if(dfn[y=to[i]]>dfn[x]&&fa[y]!=x) build(x,y,e[i]);
}
void dfs(int x,int fa){
dep[x]=dep[f[x][0]=fa]+1;
for(int i=0;f[x][i];++i) f[x][i+1]=f[f[x][i]][i];
for(int i=h2[x];i;i=ne[i])
if(to[i]!=fa) dis[to[i]]=dis[x]+e[i],dfs(to[i],x);
}
inline int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=14;~i;--i)
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
for(int i=14;~i;--i)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
A=x,B=y;
return f[x][0];
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>q;
int x,y,z;
for(int i=1;i<=m;++i)
cin>>x>>y>>z,add(h1,x,y,z),add(h1,y,x,z);
node=n;
tarjan(1,0);
dfs(1,0);
while(q--){
cin>>x>>y;
z=lca(x,y);
//lca是圆点
if(z<=n) cout<<dis[x]+dis[y]-2*dis[z]<<endl;
//lca是方点
else{
int res=dis[x]-dis[A]+dis[y]-dis[B];
res+=min(abs(s[A]-s[B]),sum[A]-abs(s[A]-s[B]));
cout<<res<<endl;
}
}
}
最大流
// Problem: P3376 【模板】网络最大流
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3376
// Memory Limit: 128 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,INF=1e18;
int tot=1,ne[N],head[N],e[N],to[N];
int cur[N],d[N];
inline void add(int x,int y,int w){
e[++tot]=w,ne[tot]=head[x],head[x]=tot,to[tot]=y;
}
int n,m,s,t;
int q[N],l,r;
inline bool bfs(){
for(int i=1;i<=n;++i) d[i]=INF,cur[i]=head[i];
d[s]=1,q[l=r=1]=s;
while(l<=r){
int x=q[l++];
for(int i=head[x];i;i=ne[i])
if(e[i]&&d[to[i]]>d[x]+1) d[to[i]]=d[x]+1,q[++r]=to[i];
}
return d[t]!=INF;
}
inline int dinic(int x,int flow){
if(x==t) return flow;
int used=0;
for(int y,&i=cur[x];i;i=ne[i])
if(e[i]&&d[y=to[i]]==d[x]+1){
int k=dinic(y,min(flow-used,e[i]));
e[i]-=k,e[i^1]+=k,used+=k;
if(used==flow) break;
}
return used;
}
inline int Dinic(){
int ans=0,x;
while(bfs())
while(x=dinic(s,INF)) ans+=x;
return ans;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>s>>t;
for(int i=1,u,v,w;i<=m;++i)
cin>>u>>v>>w,add(u,v,w),add(v,u,0);
cout<<Dinic()<<endl;
}
最小费用最大流
// Problem: P3381 【模板】最小费用最大流
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3381
// Memory Limit: 128 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,INF=1e18;
int tot=1,ne[N],head[N],e[N],to[N],w[N];
int cur[N],d[N];
inline void add(int x,int y,int W,int E){
e[++tot]=W,ne[tot]=head[x],head[x]=tot,to[tot]=y,w[tot]=E;
}
int n,m,s,t;
int q[N],l,r,vis[N];
inline bool spfa(){
for(int i=1;i<=n;++i) d[i]=INF,cur[i]=head[i],vis[i]=0;
d[s]=0,q[l=r=1]=s;
while(l<=r){
int x=q[l++];vis[x]=0;
for(int i=head[x];i;i=ne[i])
if(e[i]&&d[to[i]]>d[x]+w[i]){
d[to[i]]=d[x]+w[i];
if(!vis[to[i]]) vis[to[i]]=1,q[++r]=to[i];
}
}
return d[t]!=INF;
}
int ans,res;
inline int dinic(int x,int flow){
vis[x]=1;
if(x==t) return ans+=flow,res+=flow*d[t],flow;
int used=0;
for(int y,&i=cur[x];i;i=ne[i])
if((!vis[y=to[i]]||y==t)&&e[i]&&d[y]==d[x]+w[i]){
int k=dinic(y,min(flow-used,e[i]));
e[i]-=k,e[i^1]+=k,used+=k;
if(used==flow) break;
}
return used;
}
inline void Dinic(){
while(spfa()){
vis[t]=1;
while(vis[t]) vis[t]=0,dinic(s,INF);
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>s>>t;
for(int i=1,u,v,w,E;i<=m;++i)
cin>>u>>v>>w>>E,add(u,v,w,E),add(v,u,0,-E);
Dinic();
cout<<ans<<" "<<res<<endl;
}
数学
exgcd
#define ll long long
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b) return d=a,x=1,y=0,void();
exgcd(b,a%b,d,y,x),y-=a/b*x;
}
乘法逆元
namespace Inv{
void exgcd(int a,int b,int &d,int &x,int &y){
if(!b) return d=a,x=1,y=0,void();
exgcd(b,a%b,d,y,x),y-=a/b*x;
}
int a,b,d,x,y;
inline int Inv(int a,int mod,int v=1){
exgcd(a,mod,d,x,y);
assert(v%d==0),x*=v/d;
return (x%mod+mod)%mod;
}
}
EXCRT
namespace ExCRT{
void exgcd(int a,int b,int &d,int &x,int &y){
if(!b) return d=a,x=1,y=0,void();
exgcd(b,a%b,d,y,x),y-=a/b*x;
}
int d,x,y;
int solve(int n,int *a,int *b,int *p){
int ans=0,P=1;
for(int i=1;i<=n;++i){
exgcd(a[i]*P,p[i],d,x,y);
if(((b[i]-ans*a[i])%d)) return -1;
ans=(ans+(b[i]-ans*a[i])/d*x*P),P=P*p[i]/d;
ans=(ans%P+P)%P;
}
return ans;
}
}
Lucas
namespace Lucas{
inline int binom(int n,int m){
return (n<m||m<0)?0:1ll*fac[n]*ifac[n-m]%mod*ifac[m]%mod;
}
inline int lucas(int n,int m){
if(m>n) return 0;
if(m==0) return 1;
return binom(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
inline void init(){
fac[0]=fac[1]=inv[0]=inv[1]=ifac[0]=ifac[1]=1;
for(int i=2;i<N;++i)
fac[i]=fac[i-1]*1ll*i%mod,
inv[i]=(mod-mod/i)*inv[mod%i]%mod,
ifac[i]=ifac[i-1]*inv[i]%mod;
}
}
exLucas
namespace exLucas{
inline int qpow(int a,int b,int mod){
int ans=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1) ans=ans*a%mod;
return ans;
}
void exgcd(int a,int b,int &d,int &x,int &y){
if(!b) return d=a,x=1,y=0,void();
exgcd(b,a%b,d,y,x),y-=a/b*x;
}
inline int Inv(int a,int mod,int v=1){
int d,x,y;
exgcd(a,mod,d,x,y),x*=v/d;
return (x%mod+mod)%mod;
}
namespace ExCRT{
int d,x,y;
int solve(int n,int *a,int *b,int *p){
int ans=0,P=1;
for(int i=1;i<=n;++i){
exgcd(a[i]*P,p[i],d,x,y);
if(((b[i]-ans*a[i])%d)) return -1;
ans=(ans+(b[i]-ans*a[i])/d*x*P),P=P*p[i]/d;
ans=(ans%P+P)%P;
}
return ans;
}
}
int fac[N];
inline int getfac(int x,int p,int pw){
if(x<=p) return fac[x];
return fac[x%pw]*qpow(fac[pw],x/pw,pw)%pw*getfac(x/p,p,pw)%pw;
}
inline int getans(int n,int m,int p,int pw){
fac[0]=1;
for(int i=1;i<=pw;++i)
if(i%p) fac[i]=fac[i-1]*i%pw;
else fac[i]=fac[i-1];
int degp=0,up=getfac(n,p,pw),dow=getfac(m,p,pw)*getfac(n-m,p,pw)%pw;
for(int x=n;x;x/=p) degp+=x/p;
for(int x=n-m;x;x/=p) degp-=x/p;
for(int x=m;x;x/=p) degp-=x/p;
return qpow(p,degp,pw)*up%pw*Inv(dow,pw)%pw;
}
int pr[N],pw[N],cnt;
int a[N],b[N],p[N];
inline int solve(int n,int m,int mod){
int tmp=mod,lim=sqrt(mod)+5;
for(int i=2;i<=lim;++i)
if(tmp%i==0){
pr[++cnt]=i,pw[cnt]=1;
while(tmp%i==0) pw[cnt]*=i,tmp/=i;
}
if(tmp>1) pr[++cnt]=tmp,pw[cnt]=tmp;
for(int i=1;i<=cnt;++i)
b[i]=getans(n,m,pr[i],pw[i]),p[i]=pw[i];
for(int i=1;i<=cnt;++i)
a[i]=1,b[i]%=p[i];
return ExCRT::solve(cnt,a,b,p);
}
}
类欧几里得算法
// Problem: P5170 【模板】类欧几里得算法
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5170
// Memory Limit: 125 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353,Inv2=499122177,Inv6=166374059;
inline int S1(int n){return n*(n+1)%mod*Inv2%mod;}
inline int S2(int n){return n*(n+1)%mod*(2*n+1)%mod*Inv6%mod;}
inline int md(int x){return (x%mod+mod)%mod;}
struct node{
int a,b,c;
inline node (int x=0,int y=0,int z=0){a=md(x),b=md(y),c=md(z);}
};
inline int pf(int x){return x*x%mod;}
node ask(int a,int b,int c,int n){
int aa=a/c,bb=b/c,ans1,ans2,ans3;
if(!a){
ans1=(n+1)*bb,ans2=(n+1)*pf(bb),ans3=S1(n)*bb;
return node(ans1,ans2,ans3);
}
if(aa||bb){
node tmp=ask(a%c,b%c,c,n);
ans1=S1(n)*aa+(n+1)*bb+tmp.a;
ans2=tmp.b+md(2*aa*tmp.c)+md(2*bb*tmp.a)+S2(n)*pf(aa)+(n+1)*pf(bb)+md(n*(n+1))*md(aa*bb);
ans3=tmp.c+S2(n)*aa+S1(n)*bb;
return node(ans1,ans2,ans3);
}
int m=(a*n+b)/c;
node tmp=ask(c,c-b-1,a,m-1);
ans1=n*m-tmp.a;
ans2=n*m%mod*(m+1)-ans1-2*tmp.c-2*tmp.a;
ans3=n*m%mod*(n+1)-tmp.b-tmp.a;
return node(ans1,ans2,ans3%mod*Inv2);
}
int T,n,a,b,c;
node ans;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--)
cin>>n>>a>>b>>c,ans=ask(a,b,c,n),cout<<ans.a<<" "<<ans.b<<" "<<ans.c<<endl;
}
高斯消元
#include<bits/stdc++.h>
#define db double
using namespace std;
const db eps=1e-7;
const int N=55;
int n;
db a[N][N];
inline int gauss(){
int c,r;
for(c=r=1;c<=n;++c){
int t=r;
for(int i=r+1;i<=n;++i)
if(fabs(a[t][c])<fabs(a[i][c])) t=i;
if(fabs(a[t][c])<eps) continue;
swap(a[t],a[r]);
for(int i=n+1;i>=c;--i) a[r][i]/=a[r][c];
for(int i=1;i<=n;++i)
if(i!=r) for(int j=n+1;j>=c;--j) a[i][j]-=a[r][j]*a[i][c];
++r;
}
if(r<=n){
for(int i=r;i<=n;++i)
if(fabs(a[i][n+1])>eps) return 2;
return 0;
}
return 1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
for(int j=1;j<=n+1;++j) cin>>a[i][j];
int opt=gauss();
if(opt==1) for(int i=1;i<=n;++i) printf("x%d=%.2lf\n",i,a[i][n+1]);
else if(opt==2) printf("-1");
else printf("0");
return 0;
}
行列式求值
// Problem: P7112 【模板】行列式求值
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7112
// Memory Limit: 64 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int N=605;
int a[N][N],n,mod;
inline int md(int x){return x>=mod?x-mod:x;}
inline int solve(){
int ans=1,f=1;
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j){
while(a[i][i]){
int div=a[j][i]/a[i][i];
for(int k=i;k<=n;++k)
a[j][k]=md(a[j][k]-1ll*div*a[i][k]%mod+mod);
swap(a[i],a[j]),f=-f;
}
swap(a[i],a[j]),f=-f;
}
for(int i=1;i<=n;++i) ans=1ll*ans*a[i][i]%mod;
return md(ans*f+mod);
}
signed main(){
cin>>n>>mod;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) cin>>a[i][j],a[i][j]%=mod;
cout<<solve()<<endl;
}
矩阵求逆
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=405,mod=1e9+7;
int a[N][N<<1],n;
inline int inv(int a,int b=mod-2){
int ans=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1) ans=ans*a%mod;
return ans;
}
inline int solve(){
for(int i=1;i<=n;++i){
int r=i;
for(int j=r+1;j<=n;++j)
if(a[j][i]>a[r][i]) r=j;
if(i!=r) swap(a[r],a[i]);
if(!a[i][i]) return 0;
int Inv=inv(a[i][i]);
for(int j=1;j<=n;++j)
if(j!=i){
int p=a[j][i]*Inv%mod;
for(int k=i;k<=n*2;++k)
a[j][k]=(a[j][k]-p*a[i][k]%mod+mod)%mod;
}
for(int j=1;j<=n*2;++j) a[i][j]=a[i][j]*Inv%mod;
}
return 1;
}
signed main(){
cin>>n;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) cin>>a[i][j],a[i][i+n]=1;
int opt=solve();
if(opt==0) return cout<<"No Solution"<<endl,0;
for(int i=1;i<=n;++i,cout<<endl)
for(int j=1;j<=n;++j) cout<<a[i][j+n]<<" ";
}
Matrix-Tree 定理
// Problem: P6178 【模板】Matrix-Tree 定理
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6178
// Memory Limit: 250 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=605,mod=1e9+7;
int a[N][N],n;
inline int md(int x){return (x%mod+mod)%mod;}
inline int solve(){
int ans=1,f=1;
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j){
while(a[i][i]){
int div=a[j][i]/a[i][i];
for(int k=i;k<=n;++k)
a[j][k]=md(a[j][k]-div*a[i][k]);
swap(a[i],a[j]),f=-f;
}
swap(a[i],a[j]),f=-f;
}
for(int i=1;i<=n;++i) ans=ans*a[i][i]%mod;
return md(ans*f);
}
int m,opt;
signed main(){
cin>>n>>m>>opt,opt^=1,--n;
int u,v,w;
while(m--)
cin>>u>>v>>w,--u,--v,
a[u][u]+=w*opt,a[v][v]+=w,
a[u][v]-=w*opt,a[v][u]-=w;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) a[i][j]=md(a[i][j]);
cout<<solve()<<endl;
}
杜教筛
#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
unordered_map<int,int>Sp,Smu;
const int N=2e6+5;
bitset<N>st;
int pr[N],cnt;
ll mu[N],phi[N];
inline void pre()
{
mu[1]=phi[1]=1;
for(int i=2;i<N;++i)
{
if(!st[i]) pr[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(int j=1;i*pr[j]<N;++j)
{
st[i*pr[j]]=1;
if(i%pr[j]) phi[i*pr[j]]=1ll*phi[i]*(pr[j]-1),mu[i*pr[j]]=-mu[i];
else phi[i*pr[j]]=1ll*phi[i]*pr[j];
if(i%pr[j]==0) break;
}
}
for(int i=1;i<N;++i) phi[i]+=phi[i-1],mu[i]+=mu[i-1];
}
ll getphi(int n)
{
if(n<N) return phi[n];
if(Sp[n]) return Sp[n];
ll res=1ll*n*(n+1)/2;
for(int l=2,r;l<=n;l=r+1)
r=n/(n/l),res-=1ll*(r-l+1)*getphi(n/l);
return Sp[n]=res;
}
ll getmu(int n)
{
if(n<N) return mu[n];
if(Smu[n]) return Smu[n];
ll res=1;
for(int l=2,r;l<=n;l=r+1)
r=n/(n/l),res-=1ll*(r-l+1)*getmu(n/l);
return Smu[n]=res;
}
int n,T;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
pre();
while(T--)
cin>>n,cout<<getphi(n)<<" "<<getmu(n)<<endl;
}
标签:return,int,void,low,整理,inline,模板,mod
From: https://www.cnblogs.com/Nityacke/p/17814262.html