板子合集
WeLikeStudying · · 个人记录
计算几何
二维凸包
#include<bits/stdc++.h>
#define up(a,b,c) for(int a=b;a<=c;++a)
const int N=11e4;
using namespace std;
int n,m;
double rs;
struct ppt
{
double x,y;
void inp()
{
cin>>x>>y;
}
ppt operator - (ppt b)
{
return {x-b.x,y-b.y};
}
double sq()
{
return sqrt(x*x+y*y);
}
double operator * (ppt b)
{
return x*b.y-y*b.x;
}
}e[N];
bool cmp(ppt a,ppt b)
{
double x=(a-e[1])*(b-e[1]);
return x==0?(a-e[1]).sq()<(b-e[1]).sq():x>0;
}
int main()
{
cin>>n;
up(i,1,n)
{
e[i].inp();
if(e[i].x<e[1].x||(e[i].x==e[1].x&&e[i].y>e[1].y))swap(e[i],e[1]);
}
sort(e+2,e+n+1,cmp);
m=1;
up(i,2,n)
{
while(m>1&&(e[i]-e[m])*(e[m]-e[m-1])>=0)--m;
swap(e[++m],e[i]);
}
up(i,1,m)rs+=(e[i]-e[i%m+1]).sq();
printf("%.2lf",rs);
return 0;
}
半平面交
#include<bits/stdc++.h>
#define up(a,b,c)for(int a=b;a<=c;++a)
const int N=55e4;
using namespace std;
struct pt
{
double x,y;
pt operator-(const pt &b)const{return {x-b.x,y-b.y};}
double operator*(const pt &b)const
{
return x*b.y-y*b.x;
}
double arg() const
{
return atan2(y,x);
}
void in()
{
cin>>x>>y;
}
}p[N],q[N];
double xt(const pt &o,const pt &a,const pt &b)
{
return (a-o)*(b-o);
}
struct ln
{
pt s,e;
double ag;
double arg() const
{
return ag;
}
void in(pt S,pt E)
{
e=E,s=S,ag=(E-S).arg();
}
bool operator < (const ln &B) const
{
if(ag==B.ag)
return xt(s,B.s,B.e)>0;
return ag<B.ag;
}
pt operator * (const ln &B) const
{
double S1=xt(s,B.e,e),S2=xt(s,B.s,e);
return {(S1*B.s.x-S2*B.e.x)/(S1-S2),(S1*B.s.y-S2*B.e.y)/(S1-S2)};
}
}e[N],dq[N];
bool ck(const ln &A,const ln &B,const ln &C)
{
return xt(B*C,A.s,A.e)<0;
}
int n,m,s,l;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
{
int n,m;cin>>n;
while(n--)
{
cin>>m;
up(i,1,m)p[i].in();
up(i,1,m)e[++::n].in(p[i],p[i%m+1]);
}
}
sort(e+1,e+n+1);
m=1;
up(i,2,n)
if(e[i].arg()>e[i-1].arg())
e[++m]=e[i];
s=2,l=1;
dq[1]=e[1];
dq[2]=e[2];
up(i,3,m)
{
while(l<s&&ck(e[i],dq[s],dq[s-1]))--s;
while(l<s&&ck(e[i],dq[l],dq[l+1]))++l;
dq[++s]=e[i];
}
while(l<s&&ck(dq[l],dq[s],dq[s-1]))--s;
while(l<s&&ck(dq[s],dq[l],dq[l+1]))++l;
up(i,l,s-1)q[i-l+1]=dq[i]*dq[i+1];
if(s-l>1)q[s-l+1]=dq[s]*dq[l],m=s-l+1;
else m=0;
double ans=0;
up(i,1,m)ans+=q[i]*q[i%m+1];
cout<<fixed<<setprecision(3)<<ans/2.;
return 0;
}
闵可夫斯基和
#include<bits/stdc++.h>
#define up(a,b,c) for(int a=b;a<=c;++a)
const int N=11e4;
using namespace std;
int n,m,k,tp,tt;
struct pt
{
double x,y;
void in()
{
cin>>x>>y;
}
pt operator + (pt b)
{
return {x+b.x,y+b.y};
}
pt operator - (pt b)
{
return {x-b.x,y-b.y};
}
double operator ^ (pt b)
{
return x*b.x+y*b.y;
}
double operator * (pt b)
{
return x*b.y-y*b.x;
}
double sq()
{
return sqrt(x*x+y*y);
}
}o,p[N],q[N],f[N],g[N],A[N];
bool cmp(pt a,pt b)
{
double x=(a-o)*(b-o);
return x==0?(a-o).sq()<(b-o).sq():x>0;
}
void conv(pt *e,int &n)
{
up(i,1,n)
if(e[i].x<e[1].x||(e[i].x==e[1].x&&e[i].y>e[1].y))swap(e[i],e[1]);
o=e[1],sort(e+2,e+n+1,cmp);
int m=1;
up(i,2,n)
{
while(m>1&&(e[i]-e[m])*(e[m]-e[m-1])>=0)--m;
swap(e[++m],e[i]);
}
n=m;
}
void mkfsj()
{
up(i,1,n)f[i]=p[i%n+1]-p[i];
up(i,1,m)g[i]=q[i%m+1]-q[i];
A[tt=1]=p[1]+q[1];
int s=1,l=1;o={0,0};
while(s<=n&&l<=m)++tt,A[tt]=A[tt-1]+(cmp(f[s],g[l])?f[s++]:g[l++]);
while(s<=n)++tt,A[tt]=A[tt-1]+f[s++];
while(l<=m)++tt,A[tt]=A[tt-1]+g[l++];
conv(A,tt);
}
bool li(pt a)
{
if(a*A[2]>0||(a*A[2]==0&&a.sq()>A[2].sq()))return 0;
if(a*A[tt]<0||(a*A[tt]==0&&a.sq()>A[tt].sq()))return 0;
int i=lower_bound(A+2,A+tt+1,a,cmp)-A-1;
return (a-A[i])*(A[i%tt+1]-A[i])<=0;
}
int main()
{
cin>>n>>m>>k;
up(i,1,n)p[i].in();conv(p,n);
o={0,0};up(i,1,m)q[i].in(),q[i]=o-q[i];conv(q,m);
mkfsj(),o={0,0};
pt e=A[1];up(i,1,tt)A[i]=A[i]-e;
while(k--)A[0].in(),cout<<li(A[0]-e)<<'\n';
return 0;
}
字符串
KMP
#include<fstream>
#include<cstring>
const int N=1100000;
using namespace std;
int n,m,fl[N];
char s[N],t[N];
int main()
{
scanf("%s%s",t,s);
n=strlen(t),m=strlen(s);
int k=fl[0]=fl[1]=0;
for(int i=2;i<=m;++i)
{
while(k&&s[i-1]!=s[k])k=fl[k];
if(s[i-1]==s[k])++k;
fl[i]=k;
}
k=0;
for(int i=1;i<=n;++i)
{
while(k&&t[i-1]!=s[k])k=fl[k];
if(t[i-1]==s[k])++k;
if(k==m)printf("%d\n",i-m+1),k=fl[k];
}
for(int i=1;i<=m;++i)printf("%d ",fl[i]);
return 0;
}
Z 函数
#include<fstream>
#include<cstring>
const int N=22000000;
using namespace std;
int n,m,z[N],p[N];
char t[N],s[N];
inline void Z_fuc(char *s,char *t,int *p,int n,int m)
{
*p=0;
while(*p<n&&*p<m&&t[*p]==s[*p])++(*p);
for(int i=1,l=0,r=1;i<n;++i)
{
p[i]=i+z[i-l]<r?z[i-l]:max(0,r-i);
while(p[i]<m&&i+p[i]<n&&t[p[i]]==s[i+p[i]])++p[i];
if(i+p[i]>r)l=i,r=i+p[i];
}
}
inline void print(int *p,int n)
{
long long ans=0;
for(int i=0;i<n;++i)ans^=1ll*(i+1)*(p[i]+1);
printf("%lld\n",ans);
}
int main()
{
scanf("%s%s",t,s);
n=strlen(t),m=strlen(s);
Z_fuc(s,s,z,m,m);print(z,m);
Z_fuc(t,s,p,n,m);print(p,n);
return 0;
}
manacher
#include<fstream>
#include<cstring>
const int N=23000000;
using namespace std;
int n,d[N];
char s[N];
int main()
{
scanf("%s",s);n=strlen(s);
for(int i=n-1;i>=0;--i)s[i<<1|1]=s[i];
for(int i=0;i<=n;++i)s[i<<1]='\0';
n=n<<1|1;
for(int i=0,x=0,r=0;i<n;++i)
if(i<r&&i+d[(x<<1)-i]<r)d[i]=d[(x<<1)-i];
else
{
d[i]=max(0,r-i);
while(d[i]<=i&&i+d[i]<n&&s[i-d[i]]==s[i+d[i]])++d[i];
x=i,r=i+d[i]-1;
}
int ans=0;
for(int i=0;i<n;++i)ans=max(ans,d[i]-1);
printf("%d",ans);
return 0;
}
AC 自动机
#include<fstream>
const int N=1100000,L=26;
using namespace std;
int n,rt,ans,nd,st,fl[N],g[N],sn[N][L],qwq[N];
bool ok[N];
char s[N];
void insert(char *s)
{
int *u=&rt;
while(*s!='\0')
{
if(!*u)*u=++nd;
u=&sn[*u][*s-'a'];
++s;
}
if(!*u)*u=++nd;
++g[*u];
}
void ac_auto()
{
int l=0,r=1;
fl[rt]=rt;
for(int j=0;j<L;++j)
if(sn[rt][j])fl[qwq[r++]=sn[rt][j]]=rt;
else sn[rt][j]=rt;
while(l<r)
for(int j=0,u=qwq[l++];j<L;++j)
if(sn[u][j])
fl[qwq[r++]=sn[u][j]]=sn[fl[u]][j];
else
sn[u][j]=sn[fl[u]][j];
}
void run(char *s)
{
int u=rt;
while(*s!='\0')
{
u=sn[u][*(s++)-'a'];
for(int z=u;!ok[z]&&z!=fl[z];z=fl[z])
ans+=g[z],ok[z]=1;
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i)
{
scanf("%s",s);
insert(s);
}
ac_auto();
scanf("%s",s);
run(s);
printf("%d",ans);
return 0;
}
后缀数组
#include<fstream>
#include<cstring>
#include<algorithm>
const int N=55000,L=16;
using namespace std;
int n;
struct SA
{
char s[N];
int sa[N],rk[N],h[N],bu[N],c[N],lg[N],mx[N][L];
bool cmp(int i,int j)
{
return rk[i]==rk[j]?c[i]<c[j]:rk[i]<rk[j];
}
void sort(int k)
{
fill(bu,bu+k+1,0);
for(int j=0;j<n;++j)++bu[rk[sa[j]]];
for(int j=1;j<=k;++j)bu[j]+=bu[j-1];
for(int j=n-1;j>=0;--j)c[--bu[rk[sa[j]]]]=sa[j];
copy(c,c+n,sa);
}
void calc()
{
for(int i=0;i<n;++i)sa[i]=i,rk[i]=s[i]-'a';
sort(1);fill(c,c+n,0);
for(int i=1,k;i<n;i<<=1)
{
k=0;
for(int j=0;j<n;++j)
rk[sa[j]]=j+1<n&&cmp(sa[j],sa[j+1])?k++:k;
if(k==n)continue;
for(int j=0;j<i;++j)c[j]=n-i+j;
for(int j=0,t=i;j<n;++j)
if(sa[j]>=i)c[t++]=sa[j]-i;
copy(c,c+n,sa);sort(k);
for(int j=0;j<n;++j)
c[j]=i+j<n?rk[i+j]+1:0;
}
for(int i=0;i<n;++i)rk[sa[i]]=i;
for(int i=0,k=0;i<n;++i)
{
if(!rk[i])continue;
if(k)--k;
int pe=sa[rk[i]-1];
while(i+k<n&&pe+k<n&&s[i+k]==s[pe+k])++k;
h[rk[i]]=k;
}
lg[0]=-1;
for(int i=1;i<=n;++i)lg[i]=lg[i>>1]+1,mx[i-1][0]=h[i-1];
for(int i=1;i<=lg[n];++i)
for(int j=0;j+(1<<i)<=n;++j)
mx[j][i]=min(mx[j][i-1],mx[j+(1<<i-1)][i-1]);
}
int LCP(int x,int y)
{
int l=rk[x],r=rk[y];
if(l>r)swap(l,r);
int L=lg[r-l];
return min(mx[l+1][L],mx[r-(1<<L)+1][L]);
}
}lcp,lcs;
void solve()
{
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf(" %c",&lcp.s[i]);
copy(lcp.s,lcp.s+n,lcs.s);
reverse(lcs.s,lcs.s+n);
lcp.calc(),lcs.calc();
int res=1;
for(int i=1;i<=n;++i)
for(int j=0;j+i<n;j+=i)
res=max(res,(lcp.LCP(j,j+i)+lcs.LCP(n-j-1,n-j-i-1)-1)/i+1);
printf("%d\n",res);
}
int main()
{
int T;scanf("%d",&T);
while(T--)solve();
return 0;
}
PAM
#include<bits/stdc++.h>
const int N=550000;
using namespace std;
int n,nd,nw,fl[N],len[N],dep[N],sn[N][26];
char s[N];
int main()
{
scanf("%s",s),n=strlen(s);
len[0]=-1,nd=1;
for(int i=0,la=0;i<n;++i)
{
s[i]=(s[i]-97+la)%26;
int k=nw;
while(len[k]>=i||s[i-len[k]-1]!=s[i])k=fl[k];
if(sn[k][s[i]])la=dep[nw=sn[k][s[i]]];
else
{
len[nw=++nd]=len[k]+2;
int &g=sn[k][s[i]];
do k=fl[k];while(s[i-len[k]-1]!=s[i]);
if(sn[k][s[i]])fl[nd]=sn[k][s[i]];
else fl[nd]=1;
la=dep[nd]=dep[fl[nd]]+1,g=nd;
}
printf("%d ",la);
}
return 0;
}
图论
单源最短路
#include<bits/stdc++.h>
const int N=4e5;
const long long inf=1ll<<61;
using namespace std;
int n,m,s;
long long f[N];
#define ccf pair<long long,int>
#define w first
#define v second
#define ee(a,b) make_pair(a,b)
vector<ccf>to[N];
priority_queue<ccf,vector<ccf>,greater<ccf>>noi;
int main()
{
cin>>n>>m>>s;
for(int i=1;i<=m;++i)
{
int u,v,w;cin>>u>>v>>w;
to[u].push_back(ee(w,v));
}
fill(f,f+n+1,inf);
noi.push(ee(f[s]=0,s));
while(!noi.empty())
{
int u=noi.top().v;
long long w=noi.top().w;
noi.pop();
if(f[u]==w)
for(auto z:to[u])
if(f[z.v]>w+z.w)
noi.push(ee(f[z.v]=w+z.w,z.v));
}
for(int i=1;i<=n;++i)cout<<(f[i]<inf?f[i]:-1)<<' ';
return 0;
}
差分约束
#include<fstream>
const int N=5500,M=11000,INF=1000000000;
using namespace std;
int n,m,tl;
long long dis[N];
struct edge
{
int u,v,w;
}e[M];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)dis[i]=INF;
dis[0]=0;
for(tl=0;tl<n;++tl)
e[tl].u=0,e[tl].v=tl+1,e[tl].w=0;
for(int i=0;i<m;++i)
scanf("%d%d%d",&e[tl+i].v,&e[tl+i].u,&e[tl+i].w);
tl+=m;
int i;
for(i=0;i<=n;++i)
{
bool p=0;
for(int j=0;j<tl;++j)
if(dis[e[j].u]<INF&&dis[e[j].v]>dis[e[j].u]+e[j].w)
dis[e[j].v]=dis[e[j].u]+e[j].w,p=1;
if(!p)break;
}
if(i<=n)
for(int j=1;j<=n;++j)
printf("%lld ",dis[j]);
else printf("NO");
return 0;
}
欧拉回路
#include<bits/stdc++.h>
const int N=22e4;
using namespace std;
int t,n,m,u[N],v[N];
bool vis[N];
vector<int>to[N],res;
void dfs(int U)
{
int x,z,V;
while(!to[U].empty())
{
z=to[U].back(),to[U].pop_back();
if(!vis[x=abs(z)])
vis[x]=1,V=u[x]^U^v[x],dfs(V),res.push_back(z);
}
}
int main()
{
scanf("%d%d%d",&t,&n,&m);
int x=0,y,g;
for(int i=1;i<=m;++i)
{
scanf("%d%d",&u[i],&v[i]),x=u[i];
to[u[i]].push_back(i);
if(t==1)to[v[i]].push_back(-i);
}
dfs(y=x);
bool ok=0;
for(int z:res)
{
g=abs(z);
if(z<0&&y!=u[g])ok=1;
if(z>0&&y!=v[g])ok=1;
y^=u[g]^v[g];
}
if(res.size()<m||ok||y!=x)puts("NO");
else
{
puts("YES");
while(!res.empty())
printf("%d ",res.back()),res.pop_back();
}
return 0;
}
点双
#include<bits/stdc++.h>
#define up(a,b,c) for(int a=b;a<=c;++a)
const int N=55e4;
using namespace std;
int n,m,tp,ddd,bcc,dfn[N],low[N],stk[N];
vector<int>to[N],qwq[N];
void dfs(int u)
{
dfn[u]=low[u]=++ddd,stk[++tp]=u;
for(int v:to[u])
{
if(!dfn[v])
{
dfs(v),low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
++bcc;
while(stk[tp+1]!=v)
qwq[bcc].push_back(stk[tp--]);
qwq[bcc].push_back(u);
}
}
else low[u]=min(low[u],dfn[v]);
}
if(to[u].empty())qwq[++bcc].push_back(u);
}
int main()
{
cin>>n>>m;
while(m--)
{
int u,v;
cin>>u>>v;
if(u!=v)
to[u].push_back(v),
to[v].push_back(u);
}
up(i,1,n)if(!dfn[i])dfs(i);
cout<<bcc;
up(i,1,bcc)
{
cout<<'\n'<<qwq[i].size();
for(int x:qwq[i])
cout<<' '<<x;
}
return 0;
}
边双
#include<bits/stdc++.h>
#define up(a,b,c) for(int a=b;a<=c;++a)
const int N=55e4,M=22e5;
using namespace std;
int n,m,tp,ddd,dcc,r,x[M],y[M],dfn[N],low[N],bel[N],stk[N],qwq[N];
vector<int>to[N];
void dfs(int u,int la)
{
low[u]=dfn[u]=++ddd,stk[++tp]=u;
for(int z:to[u])
{
int v=u^x[z]^y[z];
if(!dfn[v])dfs(v,z),low[u]=min(low[u],low[v]);
else if(z!=la)low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
++dcc;
while(stk[tp+1]!=u)
bel[qwq[r++]=stk[tp--]]=dcc;
}
}
int main()
{
cin>>n>>m;
up(i,1,m)
cin>>x[i]>>y[i],
to[x[i]].push_back(i),
to[y[i]].push_back(i);
up(i,1,n)
if(!dfn[i])dfs(i,0);
cout<<dcc;
for(int i=0,j=1;i<r;i=j)
{
while(j<r&&bel[qwq[i]]==bel[qwq[j]])++j;
cout<<'\n'<<j-i;
up(z,i,j-1)cout<<' '<<qwq[z];
}
return 0;
}
缩点
#include<bits/stdc++.h>
const int N=11e3;
using namespace std;
struct Tarjan
{
int ddd,ins[N],low[N],dfn[N],scc,fo[N];
vector<int>to[N],used;
stack<int>pts;
void reset()
{
ddd=scc=0;
for(int u:used)
dfn[u]=0,to[u].clear();
used.clear();
}
void add(int u,int v)
{
used.push_back(u),
used.push_back(v),
to[u].push_back(v);
}
void dfs(int u)
{
dfn[u]=low[u]=++ddd,ins[u]=1,pts.push(u);
for(int v:to[u])
if(!dfn[v])
dfs(v),low[u]=min(low[u],low[v]);
else
if(ins[v])
low[u]=min(low[u],dfn[v]);
if(dfn[u]==low[u])
{
int v;
while((v=pts.top())!=u)
fo[v]=scc,ins[v]=0,pts.pop();
fo[u]=scc,ins[u]=0,pts.pop(),++scc;
}
}
void run()
{
for(int u:used)
if(!dfn[u])dfs(u);
}
}T;
int a[N],sm[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
while(m--)
{
int u,v;scanf("%d%d",&u,&v);
T.add(u,v);
}
T.run();
for(int i=1;i<=n;++i)
assert(dfn[i]),sm[T.fo[i]]+=a[i];
int res=0;
for(int i=0;i<T.scc;++i)
res=max(sm[i],res);
printf("%d",res);
return 0;
}
割点
#include<fstream>
const int N=22000,M=110000;
using namespace std;
int n,m,nm,hd[N],dfn[N],low[N];
bool pig[N];
struct edge
{
int to,nt;
}e[M<<1];
void add(int u,int v)
{
static int tl=0;
++tl;
e[tl].to=v,e[tl].nt=hd[u];
hd[u]=tl;
}
int D=0;
void dfs(int u,int f)
{
low[u]=dfn[u]=++D;
int c=0;
for(int z=hd[u];z;z=e[z].nt)
{
int v=e[z].to;
if(!dfn[v])
{
dfs(v,u);
if(u==f)++c;
else
if(low[v]>=dfn[u])pig[u]=1;
low[u]=min(low[u],low[v]);
}
else
if(v!=f)low[u]=min(low[u],dfn[v]);
}
if(c>1&&u==f)pig[u]=1;
if(pig[u])++nm;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
for(int i=1;i<=n;++i)
if(!dfn[i])dfs(i,i);
printf("%d\n",nm);
for(int i=1;i<=n;++i)
if(pig[i])printf("%d ",i);
return 0;
}
2-SAT
#include<fstream>
const int B=1100000;
using namespace std;
int n,m,hd[B<<1],dfn[B<<1],low[B<<1],wt[B<<1],stk[B<<1],ans[B],dzd,scc,top;
bool ins[B<<1],ok;
struct edge
{
int to,nt;
}e[B<<1];
void add(int u,int v)
{
static int tl=0;
++tl;
e[tl].to=v,e[tl].nt=hd[u];
hd[u]=tl;
}
void dfs(int u)
{
low[u]=dfn[u]=++dzd,ins[u]=1,stk[top++]=u;
for(int z=hd[u];z;z=e[z].nt)
{
int v=e[z].to;
if(!dfn[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else
if(ins[v])low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
while(stk[--top]!=u)
{
int v=stk[top];
ins[v]=0,wt[v]=scc;
}
ins[u]=0,wt[u]=scc++;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i)
{
int u,v,ou,ov;
scanf("%d%d%d%d",&u,&ou,&v,&ov);
add(u<<1|(!ou),v<<1|ov),
add(v<<1|(!ov),u<<1|ou);
}
for(int i=2;i<=(n<<1|1);++i)
if(!dfn[i])dfs(i);
ok=1;
// for(int i=2;i<=(n<<1|1);++i)printf("%d? ",wt[i]);
for(int i=1;i<=n&&ok;++i)
if(wt[i<<1]==wt[i<<1|1])ok=0;
else ans[i]=(wt[i<<1|1]<wt[i<<1]);
if(!ok)puts("IMPOSSIBLE");
else
{
puts("POSSIBLE");
for(int i=1;i<=n;++i)
printf("%d ",ans[i]);
}
return 0;
}
网络流
struct Dicnic
{
int n,nd,s,t,hd[N],hu[N],lvl[N],qwq[N];
const int inf=(1u<<31)-1;
struct edge
{
int v,c,nt;
}e[M];
void reset()
{
fill(hd,hd+n,-1),nd=0;
}
void add(int u,int v,int c)
{
e[nd]={v,c,hd[u]},hd[u]=nd++,
e[nd]={u,0,hd[v]},hd[v]=nd++;
}
bool bfs()
{
int l=0,r=1;
fill(lvl,lvl+n,inf),copy(hd,hd+n,hu),qwq[0]=s,lvl[s]=0;
while(l<r)
for(int u=qwq[l++],z=hd[u],v;~z;z=e[z].nt)
if(e[z].c&&lvl[u]+1<lvl[v=e[z].v])
lvl[v]=lvl[u]+1,qwq[r++]=v;
return lvl[t]<inf;
}
int dfs(int u,int fl)
{
if(u==t)return fl;
int sm=0;
for(int &z=hu[u],v;~z;z=e[z].nt)
if(e[z].c&&lvl[u]+1==lvl[v=e[z].v])
{
int c=dfs(v,min(fl,e[z].c));
fl-=c,sm+=c,e[z].c-=c,e[z^1].c+=c;
if(!fl)break;
}
return sm;
}
int flow()
{
int ans=0;
while(bfs())ans+=dfs(s,inf);
return ans;
}
}D;
最小费用流
#include<bits/stdc++.h>
using ll=long long;
const int N=55e3,M=N*10;
const ll inf=1ll<<62;
using namespace std;
int n,m,s,t,nd,flow,hd[N],hu[N];
ll d[N],h[N],cost;
struct edge
{
int v,w,c,nt;
}e[M];
struct ee
{
ll w;
int u;
bool operator < (ee b) const
{
return b.w<w;
}
};
priority_queue<ee>qwq;
void add()
{
int u,v,w,c;scanf("%d%d%d%d",&u,&v,&w,&c);
e[nd]={v,w,c,hd[u]},hd[u]=nd++,
e[nd]={u,0,-c,hd[v]},hd[v]=nd++;
}
bool bfs()
{
copy(hd,hd+n+1,hu),fill(d,d+n+1,inf);
qwq.push({d[s]=0,s});
while(!qwq.empty())
{
int u=qwq.top().u;ll w=qwq.top().w;qwq.pop();
if(d[u]<w)continue;
for(int z=hd[u];z!=-1;z=e[z].nt)
if(e[z].w&&d[e[z].v]>w+h[u]-h[e[z].v]+e[z].c)
d[e[z].v]=w+e[z].c+h[u]-h[e[z].v],
qwq.push({d[e[z].v],e[z].v});
}
return d[t]<inf;
}
bool ins[N];
int dfs(int u,int fl)
{
if(!fl||u==t)return fl;
int sm=0;ins[u]=1;
for(int &z=hu[u];z!=-1;z=e[z].nt)
if(e[z].w&&!ins[e[z].v]&&d[u]+h[u]+e[z].c-h[e[z].v]==d[e[z].v])
{
int c=dfs(e[z].v,min(fl,e[z].w));
e[z].w-=c,e[z^1].w+=c,cost+=1ll*c*e[z].c,sm+=c,fl-=c;
if(!fl)break;
}ins[u]=0;
return sm;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
fill(hd,hd+n+1,-1),fill(d,d+n+1,inf);
while(m--)add();
while(bfs())
{
flow+=dfs(s,1<<30);
for(int i=1;i<=n;++i)h[i]+=d[i];
}
printf("%d %lld\n",flow,cost);
return 0;
}
无源汇有上下界可行流
#include<bits/stdc++.h>
const int N=333,M=33333,INF=2147483647;
using namespace std;
int n,m,s,t,nd,d[N],to[N],hd[N],hu[N],lvl[N],qwq[N];
struct edge
{
int to,nt,cap;
}e[M];
void add(int u,int v,int cap)
{
e[nd]={v,hd[u],cap};hd[u]=nd++;
e[nd]={u,hd[v],0};hd[v]=nd++;
}
struct que
{
int u,v,l,r;
void read()
{
scanf("%d%d%d%d",&u,&v,&l,&r);
d[u]-=l,d[v]+=l;add(u,v,r-l);
}
}q[M];
bool bfs()
{
copy(hd,hd+n+2,hu);fill(lvl,lvl+n+2,INF);
int l=0,r=0;qwq[r++]=s,lvl[s]=0;
while(l<r)
for(int u=qwq[l++],z=hd[u];~z;z=e[z].nt)
{
int v=e[z].to;
if(lvl[u]+1<lvl[v]&&e[z].cap>0)
lvl[v]=lvl[u]+1,qwq[r++]=v;
}
return lvl[t]<INF;
}
int dfs(int u,int f)
{
if(u==t||!f)return f;
int sm=0;
for(int &z=hu[u];~z;z=e[z].nt)
{
int v=e[z].to;
if(lvl[u]+1==lvl[v]&&e[z].cap>0)
{
int c=dfs(v,min(f,e[z].cap));
e[z].cap-=c,e[z^1].cap+=c,sm+=c,f-=c;
}
if(!f)break;
}
return sm;
}
int main()
{
scanf("%d%d",&n,&m);
fill(hd,hd+n+2,-1);s=0,t=n+1;
for(int i=0;i<m;++i)q[i].read();
for(int i=1;i<=n;++i)
{
to[i]=nd;int x=d[i];
if(x>0)add(0,i,x);
else add(i,t,-x);
}
while(bfs())dfs(s,INF);
bool ok=1;
for(int i=1;i<=n;++i)
{
int x=d[i];
if(x!=0&&e[to[i]].cap>0)ok=0;
}
if(ok)
{
puts("YES");
for(int i=0;i<m;++i)
printf("%d\n",q[i].r-e[i<<1].cap);
}
else puts("NO");
return 0;
}
有源汇有上下界最大流
#include<fstream>
const int N=333,M=22222,INF=2147483647;
using namespace std;
int n,m,s,t,nd,to[N],d[N],hd[N],hu[N],lvl[N],qwq[N];
struct edge
{
int to,nt,cap;
}e[M];
void add(int u,int v,int c)
{
e[nd]={v,hd[u],c};hd[u]=nd++;
e[nd]={u,hd[v],0};hd[v]=nd++;
}
struct que
{
int u,v,l,r;
void read()
{
scanf("%d%d%d%d",&u,&v,&l,&r);
d[u]-=l,d[v]+=l,add(u,v,r-l);
}
}q[M];
bool bfs()
{
copy(hd,hd+n+2,hu);fill(lvl,lvl+n+2,INF);
int l=0,r=0;qwq[r++]=s,lvl[s]=0;
while(l<r)
for(int u=qwq[l++],z=hd[u];~z;z=e[z].nt)
{
int v=e[z].to;
if(lvl[u]+1<lvl[v]&&e[z].cap>0)
lvl[v]=lvl[u]+1,qwq[r++]=v;
}
return lvl[t]<INF;
}
int dfs(int u,int f)
{
if(u==t||!f)return f;
int sm=0;
for(int &z=hu[u];~z;z=e[z].nt)
{
int v=e[z].to;
if(lvl[u]+1==lvl[v]&&e[z].cap>0)
{
int c=dfs(v,min(f,e[z].cap));
sm+=c,f-=c,e[z].cap-=c,e[z^1].cap+=c;
if(!f)break;
}
}
return sm;
}
int dicnic()
{
int res=0;
while(bfs())res+=dfs(s,INF);
return res;
}
int main()
{
int y,h;
scanf("%d%d%d%d",&n,&m,&y,&h);s=0,t=n+1;
fill(hd,hd+n+2,-1);
for(int i=0;i<m;++i)q[i].read();
for(int i=1;i<=n;++i)
{
to[i]=nd;
if(d[i]<0)add(i,t,-d[i]);
else add(s,i,d[i]);
}
add(h,y,INF);dicnic();
bool ok=1;
for(int i=1;i<=n;++i)
if(e[to[i]].cap>0)ok=0;
if(ok)s=y,t=h,printf("%d",dicnic());
else puts("please go home to sleep");
return 0;
}
有源汇有上下界最小流
#include<fstream>
const int N=55555,M=433333,INF=2147483647;
using namespace std;
int n,m,s,t,nd,to[N],d[N],hd[N],hu[N],lvl[N],qwq[N];
struct edge
{
int to,nt,cap;
}e[M];
void add(int u,int v,int c)
{
e[nd]={v,hd[u],c};hd[u]=nd++;
e[nd]={u,hd[v],0};hd[v]=nd++;
}
struct que
{
int u,v,l,r;
void read()
{
scanf("%d%d%d%d",&u,&v,&l,&r);
d[u]-=l,d[v]+=l,add(u,v,r-l);
}
}q[M];
bool bfs()
{
copy(hd,hd+n+2,hu);fill(lvl,lvl+n+2,INF);
int l=0,r=0;qwq[r++]=s,lvl[s]=0;
while(l<r)
for(int u=qwq[l++],z=hd[u];~z;z=e[z].nt)
{
int v=e[z].to;
if(lvl[u]+1<lvl[v]&&e[z].cap>0)
{
lvl[v]=lvl[u]+1,qwq[r++]=v;
if(v==t)return 1;
}
}
return 0;
}
int dfs(int u,int f)
{
if(u==t||!f)return f;
int sm=0;
for(int &z=hu[u];~z;z=e[z].nt)
{
int v=e[z].to;
if(lvl[u]+1==lvl[v]&&e[z].cap>0)
{
int c=dfs(v,min(f,e[z].cap));
sm+=c,f-=c,e[z].cap-=c,e[z^1].cap+=c;
if(!f)break;
}
}
return sm;
}
int dicnic()
{
int res=0;
while(bfs())res+=dfs(s,INF);
return res;
}
int main()
{
int y,h;
scanf("%d%d%d%d",&n,&m,&y,&h);s=0,t=n+1;
fill(hd,hd+n+2,-1);
for(int i=0;i<m;++i)q[i].read();
for(int i=1;i<=n;++i)
{
to[i]=nd;
if(d[i]<0)add(i,t,-d[i]);
else add(s,i,d[i]);
}
add(h,y,INF);dicnic();
bool ok=1;
for(int i=1;i<=n;++i)
if(e[to[i]].cap>0)ok=0;
if(ok)
{
s=h,t=y;int giao=e[--nd].cap;
e[nd].cap=0;e[--nd].cap=0;
printf("%d",giao-dicnic());
}
else puts("please go home to sleep");
return 0;
}
数论
Pollard-rho
#include<fstream>
#include<cmath>
#define auto long long
using namespace std;
const int tl=12;
const auto p[]={2,3,5,7,11,13,17,19,23,29,31,37};
inline auto product(auto x,auto y,auto n)//防爆乘
{
register long long ans=
x*y-(long long)((long double)x*y/n+0.5)*n;//技巧性极强
return ans<0?ans+n:ans;
}
auto gcd(auto a,auto b)
{
return (b==0)?a:gcd(b,a%b);
}
inline auto power(auto x,auto a,auto mod)//快速幂的另一种写法
{
auto res;
for(res=1;a!=0;a>>=1)
{
if((a&1)!=0)res=product(res,x,mod);
x=product(x,x,mod);
}
return res;
}
inline bool Miller_Rabin(auto x)
{
if(x<=2)return x==2;//特判
auto v1=x-1;
while((v1&1)==0)v1>>=1;
for(int i=0;i<tl;i++)
{
if(x==p[i])return 1;//显然
bool ok=0;
auto v=v1;
auto y=power(p[i],v,x);
if(y==1)ok=1;
else
{
while(v<x-1)
{
if(y==x-1)
{
ok=1;
break;
}
v<<=1;
y=product(y,y,x);
}
}
if(!ok)return 0;
}
return 1;
}
inline auto big_rand()
{
static auto sd=19260817;
sd^=sd<<13;
sd^=sd>>17;
return abs(sd^=sd<<5);
}
auto seed,step;
inline auto f(auto a,auto mod)
{
return (product(a,a,mod)+seed)%mod;
}
inline auto floyd(auto n) //绕环
{
seed=big_rand()%n;
auto fast,slow,res=1;
fast=slow=big_rand()%n;
fast=f(fast,n);//注意一开始不要先跳两步
for(register int i=0;fast!=slow;i++)
{
res=product(res,fast-slow+n,n);//段取优化
if(!res)res=fast-slow+n;
if(i%step==0)
{
auto g=gcd(res,n);
if(g!=1)return g;
res=1;
}
fast=f(f(fast,n),n);
slow=f(slow,n);
}
return gcd(res,n);
}
auto mx;
void Pollard_rho(auto n)
{
if(n==1)return;
if(Miller_Rabin(n))
{
mx=max(mx,n);
return;
}
auto k=1;
step=log(n);
step=step<<1|1;
while(k==1)k=floyd(n);
Pollard_rho(k);
Pollard_rho(n/k);
}
int main()
{
int T;auto n;
scanf("%d",&T);
while(T--)
{
mx=0;
scanf("%lld",&n);
Pollard_rho(n);
if(mx!=n)printf("%lld\n",mx);
else printf("Prime\n");
}
return 0;
}
拓展欧几里得
#include<iostream>
#define auto long long
using namespace std;
auto x,y,m,n,L;
auto exgcd(auto a,auto b,auto &x,auto &y)
{
if(!b)
{
x=1;y=0;
return a;
}
auto g=exgcd(b,a%b,y,x);
y-=a/b*x;
return g;
}
int main()
{
auto a,b,c,x,y,g;
cin>>a>>b>>c;
g=exgcd(a,b,x,y);
if(c%g==0)
{
x*=c/g;y*=c/g;
cout<<"x="<<x<<' '<<"y="<<y<<endl;
}
else
cout<<"No solution."<<endl;
return 0;
}
类欧几里得
ll like_gcd(ll a,ll b,ll c,ll n) {
if(a==0)return b/c*(n+1);
if(a>=c||b>=c)return n*(n+1)/2*(a/c)+(n+1)*(b/c)+like_gcd(a%c,b%c,c,n);
ll m=(a*n+b)/c;
if(m==0)return 0;
return n*m-like_gcd(c,c-b-1,a,m-1);
}
ll g(ll,ll,ll,ll);
ll f(ll a,ll b,ll c,ll n)
{
a%=c,b%=c;
ll m=(a*n+b)/c;
return !a||!n||!m?b:min(b,a-1-g(c,c-b-1,a,m-1));
}
ll g(ll a,ll b,ll c,ll n)
{
a%=c,b%=c;
ll m=(a*n+b)/c;
return !a||!n||!m?a*n+b:max((a*n+b)%c,c-1-f(c,c-b-1,a,m-1));
}
BSGS
#include<fstream>
#include<bitset>
#include<cmath>
using namespace std;
struct hash_map
{
static const int mod=10000019;
int v[mod],p[mod];
void insert(const int key,const int a)
{
int hd=key%mod;
while(v[hd])
hd=(hd+1)%mod;
v[hd]=key;
p[hd]=a;
}
int find(const int key)
{
int hd=key%mod;
while(v[hd]!=key)
{
if(!v[hd])return 2147483647;//判断不行
hd=(hd+1)%mod;
}
return p[hd];
}
}H;
int power(int x,int p,int mod)
{
if(!p)return 1%mod;
long long res=power(x,p>>1,mod);
res=res*res%mod;
if(p&1)res=res*x%mod;
return res;
}
int main()
{
int p,b,n;
scanf("%d%d%d",&p,&b,&n);
int sq=sqrt(p),nib=power(b,p-2,p);
long long key=n,k2=power(b,sq,p);
for(int i=0;i<sq;i++)
{
// printf("%d %d\n",key,i);
H.insert(key,i);
key=key*nib%p;
}
key=1;
int ans=0;
for(int i=0;i<=sq;i++)
{
ans=H.find(key);
if(ans!=2147483647)
{
ans+=i*sq;
printf("%d",ans);
return 0;
}
key=key*k2%p;
}
printf("no solution");
return 0;
}
exBSGS
#include<fstream>
#include<map>
#include<cmath>
#define auto long long
using namespace std;
auto exgcd(auto a,auto b,auto &x,auto &y)
{
if(!b)
{
x=1;y=0;
return a;
}
auto res=exgcd(b,a%b,y,x);
y-=a/b*x;
return res;
}
auto exbsgs(auto a,auto b,auto mod)
{
a%=mod;b%=mod;//先来一组特判
int tms=0;
auto x,y,g;
while(1)
{
// printf("%lld^x=%lld(mod %lld) For %d\n",a,b==1,mod,tms);
if(b==1)return tms;
g=exgcd(a,mod,x,y);
if(g!=1)
{
tms++;
mod/=g;
if(b%g!=0)return -1;
b/=g;
exgcd(a/g,mod,x,y);
x%=mod;
if(x<0)x+=mod;
b=(b*x)%mod;
}
else
{
x%=mod;
if(x<0)x+=mod;
break;
}
}
a%=mod;
// printf("%lld^x=%lld(mod %lld) For %d\n",a,b,mod,tms);
if(mod==1)return tms;
if(b==1)return tms;
if(a==0)
{
if(b==0)return 1+tms;
return -1;
}
map<auto,int>store;
auto buc=sqrt(mod),mn=mod,val=b,wei=1;
for(int i=0;i<buc;i++)
{
if(store.find(val)!=store.end())break;
// printf("Why?Impossible!%lld\n",val);
store[val]=i;
val=val*x%mod;
wei=wei*a%mod;
}
// printf("%d\n",store[2431]);
val=1;
for(int i=0;i*buc<mod;i++)
{
map<auto,int>::iterator it=store.find(val);
if(it!=store.end())
{
auto res=i*buc+it->second+tms;
return res;
}
val=val*wei%mod;
}
if(mn<mod)return mn;
else return -1;
}
int main()
{
// printf("%lld")
auto a,p,b;
while(1)
{
scanf("%lld%lld%lld",&a,&p,&b);
if(p==0)break;
auto res=exbsgs(a,b,p);
if(res==-1)printf("No Solution\n");
else printf("%lld\n",res);
}
return 0;
}
Stern-Brocot 树
#include<bits/stdc++.h>
using ll=long long;
using namespace std;
ll m,n,ra,rb;
double r,mx;
bool ok=0;
int main()
{
ll a=0,b=1,c=1,d=0;
cin>>m>>n>>r;
ra=0,rb=1,mx=r;
while(1)
{
ll e=a+c,f=b+d,k;
if(e>m||f>n)break;
if(1.0*e/f<r)
k=(r*b-a)/(c-r*d),
e=a+=k*c,f=b+=k*d;
else
k=(c-r*d)/(r*b-a),
e=c+=k*a,f=d+=k*b;
if(abs(1.0*e/f-r)==mx)ok=1;
if(abs(1.0*e/f-r)<mx)
{
ra=e,rb=f,mx=abs(1.0*e/f-r),ok=0;
if(mx==0)break;
}
}
if(ok)puts("TOO MANY");
else printf("%lld/%lld",ra,rb);
return 0;
}
exCRT
#include<fstream>
#define ll __int128
using namespace std;
int k;
ll a[2]={0},r[2]={0};
bool fg=1;
ll gcd(ll a,ll b)
{
return (!b)?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1;y=0;
return a;
}
ll g=exgcd(b,a%b,y,x);
y-=a/b*x;
return g;
}
void check(int i,int j)
{
// if(l==a[i]*a[j])return 0;
ll x=0,y=0;
ll g=exgcd(a[i],a[j],x,y);
ll l=a[i]/g*a[j],c=r[j]-r[i];
// printf("x%%%lld=%lld\n",a[i],r[i]);
if(c%g==0)
{
x*=c/g;
ll K=a[j]/g;
x%=K;
if(x<0)x+=K;
r[i]=r[i]+a[i]*x;
a[i]=l;
}
else fg=0;
}
void input(int k)
{
if(k)
{
scanf("%lld%lld",&a[0],&r[0]);
r[0]%=a[0];
if(r[0]<0)r[0]+=a[0];
}
for(int i=1;i<k;i++)
{
scanf("%lld%lld",&a[1],&r[1]);
r[1]%=a[1];
if(r[1]<0)r[1]+=a[1];
check(0,1);
if(!fg)break;
}
if(fg)
printf("%lld\n",r[0]);
else printf("-1\n");
}
void redo()
{
fg=1;
}
int main()
{
scanf("%d",&k);
redo();
input(k);
return 0;
}
模质数二次剩余
#include<fstream>
#include<ctime>
#include<cstdlib>
using namespace std;
long long power(long long a,long long b,long long mod)
{
if(!b)return 1;
if(b==1)return a;
long long ans=power(a,b>>1,mod);
ans=ans*ans%mod;
if(b&1)ans=ans*a%mod;
return ans;
}
void cpower(long long &x,long long &y,long long b,long long a,long long w2,long long mod)//求(a+w)^b
{
if(!b)//(a+w)^0=1
{
x=1;y=0;
return;
}
// if(b==1)//(a+w)^1=a+w
// {
// x=a;y=1;
// return;
// }
long long x1=0,y1=0;
cpower(x1,y1,b>>1,a,w2,mod);
//(x1+y1*w)^2
//x1^2+2*x1*y1w+(y1*w)^2
x=(x1*x1%mod+y1*y1%mod*w2%mod)%mod;
y=x1*y1%mod*2%mod;
//(x+y*w)*(a+w)
//x*a+x*w+y*a*w+y*w2
if(b&1)
{
long long tmpx=(x*a%mod+y*w2%mod)%mod;
long long tmpy=(y*a%mod+x)%mod;
x=tmpx;
y=tmpy;
}
}
bool noroot(long long n,long long mod)
{
return power(n,(mod-1)>>1,mod)==mod-1;
}
void finda(long long &a,long long &w2,long long n,long long mod)
{
do
{
a=rand()%mod;
w2=(a*a-n)%mod;
if(w2<0)w2+=mod;
}
while(!noroot(w2,mod));
}
void solve()
{
long long n,mod;
scanf("%lld%lld",&n,&mod);
n%=mod;
if(mod==2)//0*0=0 1*1=1
printf("%lld\n",n);
else
{
if(!n)
{
printf("0\n");
return;
}
if(noroot(n,mod))
printf("Hola!\n");
else
{
long long a,w2,x,y;
finda(a,w2,n,mod);
// printf("a=%d\n",a);
// printf("w2=%d\n",w2);
cpower(x,y,(mod+1)>>1,a,w2,mod);
// printf("%d+%dw\n",x,y);
if((x<<1)<mod)
printf("%lld %lld\n",x,mod-x);
else
printf("%lld %lld\n",mod-x,x);
}
}
}
int main()
{
srand(time(NULL));
int T;
scanf("%d",&T);
while(T--)
solve();
return 0;
}
欧拉函数和莫比乌斯函数杜教筛
#include<fstream>
using namespace std;
const int MAXN=1e7+1,MAXP=664579;
int pr[MAXP],tl,miu[MAXN];
unsigned long long phi[MAXN];
bool np[MAXN];
template <typename T,typename T1>
struct hash_map
{
static const int MOD=1e7+19;
T k[MOD];
T1 v[MOD];
int nm[MOD];
hash_map()
{
for(int i=0;i<MOD;i++)
k[i]=v[i]=nm[i]=0;
}
void insert(T key,T1 value)
{
int i=key%MOD;
if(i<0)i+=MOD;
while(nm[i]>0&&k[i]!=key)i=(i+1)%MOD;
k[i]=key;
v[i]=value;
nm[i]++;
}
bool find(T key,T1 &value)
{
int i=key%MOD;
if(i<0)i+=MOD;
while(k[i]!=key)
{
if(nm[i]==0)return 0;
i=(i+1)%MOD;
}
value=v[i];
return 1;
}
};
hash_map<unsigned,unsigned long long>big_phi;
hash_map<unsigned,int>big_miu;
void linear_sieve(int n)
{
np[0]=np[1]=1;tl=0;miu[1]=phi[1]=1;
for(int i=2;i<=n;++i)
{
if(!np[i])
{
pr[tl]=i;
++tl;
miu[i]=-1;
phi[i]=i-1;
}
for(int j=0;i*pr[j]<=n;++j)
{
np[i*pr[j]]=1;
if(i%pr[j]==0)
{
miu[i*pr[j]]=0;
phi[i*pr[j]]=phi[i]*pr[j];
break;
}
miu[i*pr[j]]=miu[i]*miu[pr[j]];
phi[i*pr[j]]=phi[i]*phi[pr[j]];
}
}
for(int i=1;i<=n;++i)
{
miu[i]+=miu[i-1];
phi[i]+=phi[i-1];
}
}
unsigned long long Dr_Du_sieve_phi(unsigned n)
{
if(n<MAXN)return phi[n];
unsigned long long ans;
if(big_phi.find(n,ans))return ans;
ans=(1ull*n*(n+1))>>1;
for(unsigned l=2;l<=n;)
{
int r=n/(n/l);
ans-=Dr_Du_sieve_phi(n/l)*(r-l+1);
l=r+1;
}
big_phi.insert(n,ans);
return ans;
}
int Dr_Du_sieve_miu(unsigned n)
{
if(n<MAXN)return miu[n];
int ans;
if(big_miu.find(n,ans))return ans;
ans=1;
for(unsigned l=2;l<=n;)
{
int r=n/(n/l);
ans-=(r-l+1)*Dr_Du_sieve_miu(n/l);
l=r+1;
}
big_miu.insert(n,ans);
return ans;
}
int main()
{
linear_sieve(MAXN-1);
int T;
scanf("%d",&T);
while(T--)
{
unsigned n;
scanf("%u",&n);
printf("%llu %d\n",Dr_Du_sieve_phi(n),Dr_Du_sieve_miu(n));
}
return 0;
}
数据结构
可持久化并查集
#include<fstream>
const int N=220000,B=26214400;
using namespace std;
int n,m,tl=0,ls[B],rs[B],f[B],dp[B],rt[N];
void build(int l,int r,int &u)
{
u=++tl;
if(l==r)
{
f[u]=l,dp[u]=1;
return;
}
int mid=(l+r)>>1;
build(l,mid,ls[u]),
build(mid+1,r,rs[u]);
}
int select(int l,int r,int u,int x)
{
if(l==r)return u;
int mid=(l+r)>>1;
if(x<=mid)return select(l,mid,ls[u],x);
else return select(mid+1,r,rs[u],x);
}
void change(int l,int r,int u,int &v,int x,int y,int z)
{
if(x<l||r<x)
{
if(!v)v=u;
return;
}
v=++tl;
if(l==r)
{
f[v]=y,dp[v]=z;
return;
}
int mid=(l+r)>>1;
change(l,mid,ls[u],ls[v],x,y,z),
change(mid+1,r,rs[u],rs[v],x,y,z);
}
int fat(int k,int x)
{
int u=select(1,n,rt[k],x);
while(f[u]!=x)
{
x=f[u];
u=select(1,n,rt[k],x);
}
return u;
}
#define sam(k,x,y) (fat(k,x)==fat(k,y))
void tog(int a,int b,int x,int y)
{
int u=fat(a,x),v=fat(a,y);
if(u==v)
{
rt[b]=rt[a];
return;
}
if(dp[u]<dp[v])swap(u,v);
change(1,n,rt[a],rt[b],f[v],f[u],dp[v]);
change(1,n,rt[b],rt[b],f[u],f[u],dp[u]+(dp[u]==dp[v]));//Special
}
int main()
{
scanf("%d%d",&n,&m);
build(1,n,rt[0]);
for(int i=1;i<=m;++i)
{
int op,a,b;
scanf("%d%d",&op,&a);
if(op!=2)scanf("%d",&b);
switch(op)
{
case 3:puts(sam(i-1,a,b)?"1":"0");rt[i]=rt[i-1];break;
case 2:rt[i]=rt[a];break;
case 1:tog(i-1,i,a,b);
}
}
return 0;
}
李超树
#include<fstream>
#include<iostream>
const int N=110000,T=55000;
using namespace std;
int n;
double a[N<<2],b[N<<2];
void Add(int l,int r,int k,double A,double B)
{
if(r<l)return;
int mid=(l+r)>>1;
if(a[k]*mid+b[k]<A*mid+B)
swap(a[k],A),swap(b[k],B);
if(a[k]==A)return;
if(A<a[k])Add(l,mid-1,k<<1,A,B);
if(a[k]<A)Add(mid+1,r,k<<1|1,A,B);
}
double Query(int l,int r,int k,int x)
{
if(x<l||r<x)return 0;
int mid=(l+r)>>1;
if(x<=mid)return max(Query(l,mid-1,k<<1,x),a[k]*x+b[k]);
if(mid<x)return max(Query(mid+1,r,k<<1|1,x),a[k]*x+b[k]);
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i)
{
string op;
cin>>op;
if(op=="Project")
{
double a,b;
scanf("%lf%lf",&b,&a);
b-=a;
Add(1,T,1,a,b);
}
if(op=="Query")
{
double x;
scanf("%lf",&x);
printf("%lld\n",(long long)(Query(1,T,1,x)/100));
}
}
return 0;
}
LCT
#include<fstream>
#define l sn[0][u]
#define r sn[1][u]
#define dr(u) (sn[1][f[u]]==u)
#define nt(u) (sn[0][f[u]]==u||sn[1][f[u]]==u)
const int N=110000;
using namespace std;
int n,m,f[N],g[N],xm[N],rv[N],sn[2][N];
inline void upd(int u)
{
xm[u]=xm[l]^xm[r]^g[u];
if(l)f[l]=u;if(r)f[r]=u;
}
inline void rev(int u)
{
rv[u]^=1,swap(l,r);
}
inline void down(int u)
{
if(rv[u])
rev(l),rev(r),rv[u]=0;
}
inline void turn(int u)
{
int k=dr(u),v=f[u];
if(nt(v))sn[dr(v)][f[v]]=u;
f[u]=f[v],sn[k][v]=sn[k^1][u];
upd(v),sn[k^1][u]=v;
upd(u);
}
int st[N];
inline void splay(int u)
{
int v=u,tp;
for(tp=0;nt(v);v=f[v])st[++tp]=v;
for(st[++tp]=v;tp;--tp)down(st[tp]);
while(nt(u))
{
if(nt(f[u]))
if(dr(u)==dr(f[u]))turn(f[u]);
else turn(u);
turn(u);
}
}
inline void access(int u)
{
for(int v=0;u;v=u,u=f[u])
{
splay(u);r=v;upd(u);
}
}
inline void make_root(int u)
{
access(u);splay(u);rev(u);
}
inline void split(int u,int v)
{
make_root(u);access(v);splay(v);
}
inline int find_root(int u)
{
access(u);splay(u);
while(l)
{
down(u);u=l;
}
splay(u);return u;
}
inline void link(int u,int v)
{
make_root(u);
if(find_root(v)!=u)
f[u]=v;
}
inline void cut(int u,int v)
{
split(u,v);
if(sn[0][v]==u&&!l&&!r)
sn[0][v]=f[u]=0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&g[i]);upd(i);
}
for(int i=0,op,u,v;i<m;++i)
{
scanf("%d%d%d",&op,&u,&v);
switch(op)
{
case 0:split(u,v);printf("%d\n",xm[v]);break;
case 1:link(u,v);break;
case 2:cut(u,v);break;
default:splay(u);g[u]=v;upd(u);
}
}
return 0;
}
多项式
拉格朗日插值
#include<fstream>
const unsigned N=2200,mod=998244353;
using namespace std;
unsigned n,k,ans,x[N],y[N];
unsigned power(unsigned x,unsigned a)
{
if(a==0)return 1;
unsigned long long res=power(x,a>>1);
res=res*res%mod;
if(a&1)res=res*x%mod;
return res;
}
int main()
{
scanf("%u%u",&n,&k);
for(unsigned i=0;i<n;++i)
scanf("%u%u",&x[i],&y[i]);
for(unsigned i=0;i<n;++i)
{
unsigned long long fz=y[i],fm=1;
for(unsigned j=0;j<i;++j)fz=fz*(k+mod-x[j])%mod,fm=fm*(x[i]+mod-x[j])%mod;
for(unsigned j=i+1;j<n;++j)fz=fz*(k+mod-x[j])%mod,fm=fm*(x[i]+mod-x[j])%mod;
ans=(ans+fz*power(fm,mod-2)%mod)%mod;
}
printf("%u",ans);
return 0;
}
快速沃尔什变换
#include<fstream>
const int N=17,mod=998244353;
#define input(f) for(int S=0;S<(1<<n);++S)scanf("%d",&f[S]);
#define add(a,b) a+b>=mod?a+b-mod:a+b
#define mus(a,b) a>=b?a-b:a+mod-b
#define div2(a) (a&1)?(a+mod>>1):(a>>1)
#define cup(a,b) b=add(a,b)
#define ncup(a,b) b=mus(b,a)
#define cap(a,b) a=add(a,b)
#define ncap(a,b) a=mus(a,b)
inline void oplus(int &a,int &b)
{
int x=a,y=b;
a=add(x,y);b=mus(x,y);
}
inline void noplus(int &a,int &b)
{
oplus(a,b);
a=div2(a);b=div2(b);
}
#define FMT(f,c)\
do\
{\
for(int k=1;k<(1<<n);k<<=1)\
for(int S=0;S<(1<<n);S+=k)\
for(int i=0;i<k;++i,++S)\
c(f[S],f[S+k]);\
}\
while(0);
int n,A[1<<N],B[1<<N],a[1<<N],b[1<<N];
#define in for(int i=0;i<(1<<n);++i)a[i]=A[i],b[i]=B[i];
#define times for(int i=0;i<(1<<n);++i)a[i]=1ll*a[i]*b[i]%mod;
#define out for(int i=0;i<(1<<n);++i)printf("%d ",a[i]);puts("");
int main()
{
scanf("%d",&n);
input(A) input(B)
in FMT(a,cup) FMT(b,cup) times FMT(a,ncup) out
in FMT(a,cap) FMT(b,cap) times FMT(a,ncap) out
in FMT(a,oplus) FMT(b,oplus) times FMT(a,noplus) out
return 0;
}
子集卷积
#include<fstream>
const int N=22,U=1048576,mod=1000000009;
using namespace std;
int n,a[N][U],b[N][U],c[N][U];
#define pp(x) __builtin_popcount(x)
#define add(x,y) x+y>=mod?x+y-mod:x+y
#define mus(x,y) x>=y?x-y:x+mod-y
int main()
{
scanf("%d",&n);
int Au=1<<n;
for(int S=0;S<Au;++S)
scanf("%d",&a[pp(S)][S]);
for(int k=0;k<=n;++k)
for(int i=0;i<n;++i)
for(int S=0;S<Au;++S)
if((S>>i)&1)a[k][S]=add(a[k][S],a[k][S^(1<<i)]);
for(int S=0;S<Au;++S)
scanf("%d",&b[pp(S)][S]);
for(int k=0;k<=n;++k)
for(int i=0;i<n;++i)
for(int S=0;S<Au;++S)
if((S>>i)&1)b[k][S]=add(b[k][S],b[k][S^(1<<i)]);
for(int k=0;k<=n;++k)
for(int i=0;i<=k;++i)
for(int S=0;S<Au;++S)
c[k][S]=add(c[k][S],1ll*a[i][S]*b[k-i][S]%mod);
for(int k=0;k<=n;++k)
for(int i=0;i<n;++i)
for(int S=0;S<Au;++S)
if((S>>i)&1)c[k][S]=mus(c[k][S],c[k][S^(1<<i)]);
for(int S=0;S<Au;++S)
printf("%d ",c[pp(S)][S]);
return 0;
}
FFT
#include<bits/stdc++.h>
const int N=1<<21,mod=998244353;
using namespace std;
int n,m,L,sw[N],a[N],b[N];
long long w[N];
void dft(int *a)
{
for(int i=0;i<L;++i)if(i<sw[i])swap(a[i],a[sw[i]]);
for(int i=1;i<L;i<<=1)
for(int j=0;j<L;j+=i)
for(int k=0;k<i;++k,++j)
{
int x=a[j],y=1ll*a[j+i]*w[L/i/2*k]%mod;
a[j]=x+y>=mod?x+y-mod:x+y,
a[j+i]=x>=y?x-y:x+mod-y;
}
}
int pw(long long x,int a)
{
long long res=1;
for(;a;a>>=1,x=x*x%mod)
if(a&1)res=res*x%mod;
return res;
}
void idft(int *a)
{
long long ni=pw(L,mod-2);
for(int i=0;i<L;++i)a[i]=a[i]*ni%mod;
dft(a);
for(int i=1;i<(L>>1);++i)swap(a[i],a[L-i]);
}
int main()
{
scanf("%d%d",&n,&m);
L=1<<int(log(n+m)/log(2)+1);
w[1]=pw(3,(mod-1)/L),w[0]=1;
for(int i=1;i<L;++i)
w[i]=1ll*w[i-1]*w[1]%mod,
sw[i]=(i&1?sw[i>>1]|L:sw[i>>1])>>1;
for(int i=0;i<=n;++i)scanf("%d",&a[i]);
dft(a);
for(int i=0;i<=m;++i)scanf("%d",&b[i]);
dft(b);
for(int i=0;i<L;++i)a[i]=1ll*a[i]*b[i]%mod;
idft(a);
for(int i=0;i<=n+m;++i)printf("%d ",a[i]);
return 0;
}
特殊类型
大整数类
#include<bits/stdc++.h>
using namespace std;
namespace modint {
struct mdu {
int mod;
unsigned long long help;
mdu(int x=1) {
mod=x,help=(__int128(1)<<64)/x;
}
} mod=998244353;//g=3
inline int operator % (const long long &a,const mdu &b) {
int r=a-(__int128(b.help)*a>>64)*b.mod;
return {r>=b.mod?r-b.mod:r};
}
struct mint {
//It is suggest that don't use it in the Speed-needed place
//建议不要在需要追求时间效率的地方使用这个模板
int w;
mint(long long x=0) {
x=x%mod;
if(x<0)x+=mod.mod;
w=x;
}
bool operator == (const mint &b) const {
return w==b.w;
}
};
mint operator + (const mint &a,const mint &b) {
int x=a.w+b.w;
return {x>=mod.mod?x-mod.mod:x};
}
mint operator += (mint &a,const mint &b) {
return a=a+b;
}
mint operator - (const mint &a,const mint &b) {
int x=a.w-b.w;
return {x>=0?x:x+mod.mod};
}
mint operator -= (mint &a,const mint &b) {
return a=a-b;
}
mint operator * (const mint &a,const mint &b) {
return {1ll*a.w*b.w%mod};
}
mint operator *= (mint &a,const mint &b) {
return a=a*b;
}
mint pw(mint a,int b) {
mint res=1;
for(; b; a*=a,b>>=1)
if(b&1)res*=a;
return res;
}
int exgcd(int a,int b,int &x,int &y) {
if(!b) {
x=1,y=0;
return a;
}
int g=exgcd(b,a%b,y,x);
y-=a/b*x;
return g;
}
mint inv(mint x) {
//assert that a and mod are relatively prime
//假定 a 与模数互质
int ni,nt;
assert(exgcd(x.w,mod.mod,ni,nt)==1);
return ni;
}
mint operator / (const mint &a,const mint &b) {
return a*inv(b);
}
mint operator /= (mint &a,const mint &b) {
return a=a/b;
}
};
namespace biginteger {
using namespace modint;
struct bint {
short tp;
vector<int>s;
bint(long long x=0) {
s.clear();
if(x>0)tp=1;
if(!x)tp=0;
if(x<0)tp=-1,x=-x;
while(x) {
s.push_back(int(x%10));
x/=10;
}
reverse(s.begin(),s.end());
}
void read() {
s.clear();
int c=getchar();
tp=1;
while(!isdigit(c)) {
if(c=='-')tp=-1;
c=getchar();
}
while(isdigit(c)) {
if(!s.empty()||c!='0')s.push_back({c^'0'});
c=getchar();
}
if(s.empty())tp=0;
}
void write() {
if(!tp)putchar('0');
else {
if(tp==-1)putchar('-');
for(auto z:s)putchar(z^'0');
}
}
bool operator < (const bint &b) const {
return tp==b.tp?s.size()==b.s.size()?s<b.s:s.size()<b.s.size():tp<b.tp;
}
bool operator > (const bint &b) const {
return b<*this;
}
bool operator <= (const bint &b) const {
return !(b<*this);
}
bool operator >= (const bint &b) const {
return !(*this<b);
}
bool operator == (const bint &b) const {
return tp==b.tp&&s==b.s;
}
bool operator != (const bint &b) const {
return !(*this==b);
}
};
bint operator - (bint a) {
a.tp=-a.tp;
return a;
}
bint operator + (bint a,bint b) {
if(!a.tp)return b;
if(!b.tp)return a;
bint c;
reverse(a.s.begin(),a.s.end());
reverse(b.s.begin(),b.s.end());
if(a.tp==b.tp) {
c.tp=b.tp,c.s.resize(max(a.s.size(),b.s.size()));
int ad=0;
for(unsigned i=0; i<c.s.size(); ++i) {
if(i<a.s.size())c.s[i]+=a.s[i];
if(i<b.s.size())c.s[i]+=b.s[i];
c.s[i]+=ad;
if(c.s[i]>=10)c.s[i]-=10,ad=1;
else ad=0;
}
while(ad>0)c.s.push_back(ad%10),ad/=10;
} else {
c.tp=a.tp,c.s.resize(max(a.s.size(),b.s.size()));
for(unsigned i=0; i<c.s.size(); ++i) {
if(i<a.s.size())c.s[i]+=a.s[i];
if(i<b.s.size())c.s[i]-=b.s[i];
}
while(!c.s.empty()&&c.s.back()==0)c.s.pop_back();
if(!c.s.empty()) {
if(c.s.back()<0) {
c.tp=-c.tp;
for(auto &z:c.s)z=-z;
}
int ad=0;
for(auto &z:c.s) {
z+=ad;
if(z<0)ad=-1,z+=10;
else ad=0;
}
while(!c.s.empty()&&c.s.back()==0)c.s.pop_back();
}
if(c.s.empty())c.tp=0;
}
reverse(c.s.begin(),c.s.end());
return c;
}
bint operator += (bint &a,const bint &b) {
return a=a+b;
}
bint operator - (const bint &a,const bint &b) {
return a+-b;
}
bint operator -= (bint &a,const bint &b) {
return a=a-b;
}
static void dft(vector<mint>&a,vector<int>&sw,int L,int tp) {
//In the speed-needed place we expand the mint type
//这里在瓶颈处我们展开了 mint 类
for(int i=0; i<L; ++i)
if(i<sw[i])swap(a[i],a[sw[i]]);
for(int i=1; i<L; i<<=1) {
int g=pw(3,tp==1?(mod.mod-1)/i/2:mod.mod-1-(mod.mod-1)/i/2).w;
for(int j=0; j<L; j+=i) {
int bf=1;
for(int k=0; k<i; ++j,++k,bf=1ll*bf*g%mod) {
int x=a[j].w,y=1ll*a[j+i].w*bf%mod;
a[j]=x+y,a[j+i]=x-y;
}
}
}
if(tp==-1) {
mint ivn=inv(L);
for(int i=0; i<L; ++i)a[i]*=ivn;
}
}
bint operator * (bint a,bint b) {
if(a==0||b==0)return 0;
int L=1<<int(log(a.s.size()+b.s.size()-2)/log(2)+1);
bint c;
c.tp=a.tp*b.tp;
reverse(a.s.begin(),a.s.end());
reverse(b.s.begin(),b.s.end());
c.s.resize(a.s.size()+b.s.size()-1);
if(min(a.s.size(),b.s.size())<4*log(L))
for(unsigned i=0; i<a.s.size(); ++i)
for(unsigned j=0; j<b.s.size(); ++j)
c.s[i+j]+=a.s[i]*b.s[j];
else {
assert(L<=8388608);
//assert that L is no longer than 8388608
//假定 L 不大于 8388608
vector<mint>x(L),y(L);
vector<int>sw(L);
for(unsigned i=0; i<a.s.size(); ++i)x[i]=a.s[i];
for(unsigned i=0; i<b.s.size(); ++i)y[i]=b.s[i];
for(int i=1; i<L; ++i)sw[i]=(i&1?sw[i>>1]|L:sw[i>>1])>>1;
dft(x,sw,L,1),dft(y,sw,L,1);
for(int i=0; i<L; ++i)x[i]*=y[i];
dft(x,sw,L,-1);
for(unsigned i=0; i<c.s.size(); ++i)c.s[i]=x[i].w;
}
int ad=0;
for(auto &z:c.s)z+=ad,ad=z/10,z%=10;
while(ad>0)c.s.push_back(ad%10),ad/=10;
reverse(c.s.begin(),c.s.end());
return c;
}
bint operator *= (bint &a,const bint &b) {
return a=a*b;
}
static bint pw(bint a,int b) {
bint res=1;
for(; b; a*=a,b>>=1)
if(b&1)res*=a;
return res;
}
bint operator << (bint a,int b) {
for(int i=0; i<b; ++i)a.s.push_back(0);
return a;
}
bint operator <<= (bint &a,const int &b) {
return a=a<<b;
}
bint operator >> (bint a,int b) {
for(int i=0; i<b; ++i)
if(!a.s.empty())a.s.pop_back();
else {
a.tp=0;
break;
}
return a;
}
bint operator >>= (bint &a,const int &b) {
return a=a>>b;
}
bint barret(bint a) {
int n=a.s.size();
if(n==1)return 100/a.s[0];
if(n==2)return 10000/(10*a.s[0]+a.s[1]);
int m=n/2+1;
bint b=barret(a>>(n-m))<<(n-m);
b=(b*((bint(2)<<(n<<1))-a*b))>>(n<<1);
return b;
}
bint operator / (bint a,bint b) {
assert(b.tp);
if(!a.tp)return 0;
int m=a.s.size()-2*b.s.size();
if(m>0)a<<=m,b<<=m;
int x=a.tp*b.tp;a.tp=b.tp=1;
bint n=bint(1)<<(b.s.size()<<1),k=barret(b);
k=(k*a)>>(b.s.size()<<1);
bint g=k*b;
while(g<a)k+=1,g+=b;
while(g>a)k-=1,g-=b;
k.tp=x;
if(k.s.empty())k.tp=0;
return k;
}
bint operator /= (bint &a,const bint &b) {
return a=a/b;
}
bint operator % (const bint &a,const bint &b) {
return a-a/b*b;
}
bint operator %= (bint &a,const bint &b) {
return a=a%b;
}
bint pw(bint a,bint b,bint c) {
bint res=1;
for(; b!=0; a=a*a%c,b=b/2)
if(b.s.back()&1)res=res*a%c;
return res;
}
};
int main() {
using namespace biginteger;
srand(time(NULL));
bint a,b;
a.read(),b.read();
(a+b).write();puts("");
(a-b).write();puts("");
(a*b).write();puts("");
(a/b).write();puts("");
(a%b).write();puts("");
return 0;
}