SAM:
点击查看代码
namespace SAM
{
struct qq{int son[26],pre,step;}s[N*2];int tot,Last;
LL g[N];
void Init () {tot=Last=1;memset(s,0,sizeof(s));memset(g,0,sizeof(g));}
vector<int> vec[N];
int r[N];
void ins (int x)
{
int p=Last,np=++tot;
s[np].step=s[p].step+1;r[np]=1;
while (p!=0&&s[p].son[x]==0) s[p].son[x]=np,p=s[p].pre;
if (p==0) s[np].pre=1;
else
{
int q=s[p].son[x];
if (s[q].step==s[p].step+1) s[np].pre=q;
else
{
int nq=++tot;
s[nq]=s[q];
s[nq].step=s[p].step+1;
s[np].pre=s[q].pre=nq;
while (p!=0&&s[p].son[x]==q) s[p].son[x]=nq,p=s[p].pre;
}
}
Last=np;
}
void dfs (int x)
{
if (g[x]!=0) return ;
g[x]=r[x];
for (int u=0;u<26;u++)
{
if (s[x].son[u]!=0) dfs(s[x].son[u]);
g[x]+=g[s[x].son[u]];
}
}
void get_r (int x)
{
int siz=vec[x].size();
for (int u=0;u<siz;u++)
{
int y=vec[x][u];
get_r(y);
r[x]+=r[y];
}
}
void get_g()
{
for (int u=2;u<=tot;u++) vec[s[u].pre].push_back(u);
get_r(1);dfs(1);
}
};
多项式:
点击查看代码
#include<bits/stdc++.h>
#define modu 998244353
using namespace std;
typedef long long LL;
void add(LL &a,LL b) { a=(a+b)%modu; }
void sub(LL &a,LL b) { a=(a-b%modu+modu)%modu; }
void mul(LL &a,LL b) { a=a*b%modu; }
LL sgn(LL a) { return (a&1)?modu-1:1; }
LL pw(LL a,LL k=modu-2) {
LL ans=1;
for (;k;k>>=1) {
if (k&1)
ans=ans*a%modu;
a=a*a%modu;
}
return ans;
}
namespace polynomial {
struct poly:vector<LL> {
using vector::vector;
poly& normalize() {
while (size()&&!back())
pop_back();
return *this;
}
int deg() const { return size()-1; }
void init(int n) {
resize(n);
for (auto &x:*this)
cin>>x;
normalize();
}
poly operator - () const {
poly ans=*this;
for (auto &x:ans)
x=(modu-x)%modu;
return ans;
}
LL operator () (const LL& x) const {
LL ans=0;
for (int i=size()-1;i>=0;--i)
ans=(ans*x+at(i))%modu;
return ans;
}
};
ostream& operator << (ostream& os,poly a) {
os<<"(";
for (auto x:a) os<<x<<" ";
os<<")";
return os;
}
istream& operator >> (istream& is,poly& a) {
int n;
is>>n;
a.resize(n);
for (auto &x:a) is>>x;
return is;
}
namespace FFT {
#define maxn 1000050
int N,rev[maxn];
LL I,w[maxn];
inline void init(int n) {
for (N=1;N<n;N<<=1); I=pw(N);
assert(N<maxn);
rev[0]=0,rev[1]=N>>1;
for (int i=2;i<N;++i)
rev[i]=rev[i>>1]>>1|rev[i&1];
w[0]=1,w[1]=pw(3,(modu-1)/N);
for (int i=2;i<N;++i)
w[i]=w[i-1]*w[1]%modu;
}
inline void DFT(LL *A) {
for (int i=0;i<N;++i)
if (i<rev[i])
swap(A[i],A[rev[i]]);
for (int len=2;len<=N;len<<=1) {
int m=len>>1;
for (LL *p=A;p!=A+N;p+=len)
for (int i=0;i<m;++i) {
LL u=p[i],v=p[i+m]*w[N/len*i]%modu;
p[i]=(u+v)%modu;
p[i+m]=(u-v+modu)%modu;
}
}
}
inline void IDFT(LL *A) {
DFT(A);
reverse(A+1,A+N);
for (int i=0;i<N;++i)
mul(A[i],I);
}
}
inline poly operator + (const poly& a,const poly& b) {
poly ans(max(a.size(),b.size()));
for (int i=0;i<ans.size();++i) {
if (i<a.size()) add(ans[i],a[i]);
if (i<b.size()) add(ans[i],b[i]);
}
return ans.normalize();
}
inline poly operator - (const poly& a,const poly& b) {
poly ans(max(a.size(),b.size()));
for (int i=0;i<ans.size();++i) {
if (i<a.size()) add(ans[i],a[i]);
if (i<b.size()) sub(ans[i],b[i]);
}
return ans.normalize();
}
const int lim=300;
inline poly operator * (poly a,poly b) {
if (a.size()<lim&&b.size()<lim) {
poly ans(a.size()+b.size());
for (int i=0;i<a.size();++i)
for (int j=0;j<b.size();++j)
add(ans[i+j],a[i]*b[j]);
return ans.normalize();
} else {
FFT::init(a.size()+b.size());
a.resize(FFT::N),FFT::DFT(&a[0]);
b.resize(FFT::N),FFT::DFT(&b[0]);
for (int i=0;i<FFT::N;++i)
mul(a[i],b[i]);
FFT::IDFT(&a[0]);
return a.normalize();
}
}
inline poly operator * (poly a,LL y) {
for (auto &x:a) mul(x,y);
return a;
}
inline poly operator / (poly a,LL y) {
return a*pw(y);
}
inline poly operator % (poly a,int k) {
a.resize(k);
return a;
}
inline poly operator ~ (poly a) {//inv mod x^[a.size()+1]
poly ans={pw(a[0])};
for (int len=2;len<2*a.size();len<<=1) {
poly ta=a%len;
ans=(poly{2}-ans*ta%len)*ans;
ans.resize(len);
}
return ans%a.size();
}
inline poly operator / (poly a,poly b) {
assert(b.size());
int len=a.size()-b.size()+1;
if (len<=0) return poly{};
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
b.resize(len);
poly ans=a*(~b)%len;
reverse(ans.begin(),ans.end());
return ans.normalize();
}
inline poly operator % (poly a,poly b) {
return (a-a/b*b).normalize();
}
inline pair<poly,poly> divmod(poly a,poly b) {
poly d=a/b;
return make_pair(d,(a-d*b).normalize());
}
inline poly sqrt(poly a) {//a0=1,2*len space
poly ans={1};
for (int len=2;len<2*a.size();len<<=1) {
poly ta=a%len;
ans.resize(len);
ans=(ans/2+ta/2*~ans)%len;
}
return ans%a.size();
}
inline poly d(poly a) {
poly ans(a.size()-1);
for (int i=1;i<a.size();++i)
ans[i-1]=a[i]*i%modu;
return ans;
}
inline poly I(poly a) {
poly ans(a.size()+1);
for (int i=0;i<a.size();++i)
ans[i+1]=a[i]*pw(i+1)%modu;
return ans;
}
inline poly ln(poly a) {//a0=1
return I(d(a)*~a)%a.size();
}
inline poly exp(poly a) {//a0=0
poly ans={1};
for (int len=2;len<2*a.size();len<<=1) {
poly ta=a%len;
ans.resize(len);
ans=ans*(poly{1}-ln(ans)+ta)%len;
}
return ans%a.size();
}
inline poly operator ^ (poly a,LL k) {//a0!=0
return exp(ln(a/a[0])*k)*pw(a[0],k);
}
inline poly operator << (poly a,int k) {
poly ans(a.size()+k);
for (int i=0;i<a.size();++i)
ans[i+k]=a[i];
return ans;
}
inline poly operator >> (poly a,int k) {
if (a.size()<=k) return poly{};
poly ans(a.size()-k);
for (int i=k;i<a.size();++i)
ans[i-k]=a[i];
return ans;
}
inline vector<LL> evaluate(const poly& p,const vector<LL>& x) {
function<poly(int,int)> multi=[&](int l,int r)->poly {
if (l==r) return poly{modu-x[l],1};
int mid=(l+r)>>1;
return multi(l,mid)*multi(mid+1,r);
};
vector<LL> y(x.size());
function<void(const poly&,int,int)> calc=[&](const poly& p,int l,int r) {
if (r-l+1<=lim)
for (int i=l;i<=r;++i)
y[i]=p(x[i]);
else {
int mid=(l+r)>>1;
poly L=multi(l,mid),R=multi(mid+1,r);
calc(p%L,l,mid),calc(p%R,mid+1,r);
}
};
calc(p,0,x.size()-1);
return y;
}
inline poly interpolate(const vector<LL>& x,const vector<LL>& y) {
function<poly(int,int)> multi=[&](int l,int r)->poly {
if (l==r) return poly{-x[l],1};
int mid=(l+r)>>1;
return multi(l,mid)*multi(mid+1,r);
};
poly g=multi(0,x.size()-1);
auto c=evaluate(d(g),x);
for (int i=0;i<x.size();++i)
c[i]=y[i]*pw(c[i])%modu;
function<poly(int,int)> calc=[&](int l,int r)->poly {
if (r-l+1<=lim) {
poly ans0{1},ans1;
for (int i=l;i<=r;++i) {
poly p=poly{modu-x[i],1};
ans1=ans1*p+ans0*c[i];
ans0=ans0*p;
}
return ans1;
} else {
int mid=(l+r)>>1;
poly L=multi(l,mid),R=multi(mid+1,r);
return calc(l,mid)*R+calc(mid+1,r)*L;
}
};
return calc(0,x.size()-1);
}
//gcd
struct polyMat {
poly a0,a1,b0,b1;
/* a0 a1
b1 b1 */
polyMat(const poly& a0={},const poly& a1={},const poly& b0={},const poly& b1={}):
a0(a0),a1(a1),b0(b0),b1(b1) {}
bool operator == (const polyMat& M) const {
return a0==M.a0 && a1==M.a1 && b0==M.b0 && b1==M.b1;
}
};
const polyMat swapMat=polyMat({},{1},{1},{});
const polyMat identityMat=polyMat({1},{},{},{1});
struct polyVec {
poly a,b;
polyVec(const poly& a={},const poly& b={}):a(a),b(b) {}
};
ostream& operator << (ostream& os,const polyVec& V) {
os<<"V[ "<<V.a<<", "<<V.b<<" ]";
return os;
}
ostream& operator << (ostream& os,const polyMat& M) {
os<<"M[ "<<M.a0<<", "<<M.a1<<endl
<<" "<<M.b0<<", "<<M.b1<<" ]";
return os;
}
polyMat operator * (const polyMat& A,const polyMat& B) {
return polyMat( A.a0*B.a0+A.a1*B.b0, A.a0*B.a1+A.a1*B.b1,
A.b0*B.a0+A.b1*B.b0, A.b0*B.a1+A.b1*B.b1);
}
polyVec operator * (const polyMat& M,const polyVec& V) {
return polyVec( M.a0*V.a+M.a1*V.b, M.b0*V.a+M.b1*V.b);
}
inline polyMat hgcd(const poly& a,const poly& b) {
assert(a.size()>b.size());
int m=(a.deg()+1)>>1,n=b.deg();
if (n<m) return identityMat;
polyMat R=hgcd(a>>m,b>>m);
polyVec V=R*polyVec(a,b);
if (V.b.deg()<m) return R;
auto q=divmod(V.a,V.b);
polyMat Q({},{1},{1},-q.first);
int k=(m<<1)-V.b.deg();
return hgcd(V.b>>k,q.second>>k)*Q*R;
}
inline polyMat cogcd(const poly& a,const poly& b) {
if (!a.size()) return swapMat;
if (!b.size()) return identityMat;
if (a.size()<=b.size()) {
auto q=divmod(b,a);
polyMat Q({1},{},-q.first,{1});
return cogcd(a,q.second)*Q;
} else {
polyMat M=hgcd(a,b);
polyVec V=M*polyVec(a,b);
return cogcd(V.b,V.a)*swapMat*M;
}
};
inline poly gcd(const poly& a,const poly& b) {
polyMat M=cogcd(a,b);
polyVec V=M*polyVec(a,b);
assert(V.b==poly{});
return V.a;
}
inline poly exgcd(const poly& a,const poly& b,poly& x,poly& y) {
polyMat M=cogcd(a,b);
polyVec V=M*polyVec(a,b);
assert(V.b==poly{});
tie(x,y)=make_pair(M.a0,M.a1);
return V.a;
}
//resultant:
//let A=an*prod[i=1...n](x-ai)
//let B=bm*prod[i=1...n](x-bj)
/*R(A,B)=bm^n*prod A(bj)
=bm^n*an^m*prod_{ij}(bj-ai)
=(-1)^(nm)*an^m*prod B(ai)
*/
/* propertiy
1. R(A,B)=(-1)^(nm)*R(B,A)
2. R(A,B)=an^m*bm^n if n==0 or m==0
3. R(A-CB,B)=R(A,B) if bm==1 -> R(A,B)=R(A%B,B)
*/
inline LL resultant(const poly& a,const poly& b) {
if (!a.size()||!b.size()) return 0;
if (a.size()==1||b.size()==1)
return pw(a.back(),b.deg())*pw(b.back(),a.deg())%modu;
poly t=b/b.back();
return sgn(a.deg()*b.deg())*resultant(t,a%t)%modu*pw(b.back(),a.deg())%modu;
}
}
using namespace polynomial;
int main() {
poly a,b;
int k;
cin>>a>>b;
cout<<a+b<<endl;
cout<<a-b<<endl;
cout<<a*b<<endl;
cout<<a/b<<endl;
cout<<a%b<<endl;
cout<<(~a)<<endl;
cout<<sqrt(a)<<endl;
cout<<ln(a)<<endl;
cout<<exp(a)<<endl;
cout<<(a^k)<<endl;
cout<<gcd(a,b)<<endl;
cout<<resultant(a,b)<<endl;
}
最小树形图
点击查看代码
namespace MDT
{
vector<PI> vec[N];
int n;
LL ans,mn[N],lzy[N];
int par[N],vis[N],fa[N];
bool in[N];
int find_fa (int x) {return fa[x]==x?x:fa[x]=find_fa(fa[x]);}
bool REV (PI x,PI y) {return x.second>y.second;}
void Init (int x)
{
n=x;ans=0;
for (int u=1;u<=n;u++) fa[u]=u;
for (int u=1;u<=n;u++) sort(vec[u].begin(),vec[u].end(),REV);
}
vector<PI> Merge (int x,int y)
{
vector<PI> now;now.clear();
for (int u=0;u<=n;u++) in[u]=false;
while (!vec[x].empty()&&!vec[y].empty())
{
if (in[vec[y].back().first]) {vec[y].pop_back();continue;}
if (in[vec[x].back().first]) {vec[x].pop_back();continue;}
if (vec[y].back().second<vec[x].back().second){in[vec[y].back().first]=true;now.push_back(vec[y].back());vec[y].pop_back();}
else {in[vec[x].back().first]=true;now.push_back(vec[x].back());vec[x].pop_back();}
}
while (!vec[x].empty())
{
if (in[vec[x].back().first]) {vec[x].pop_back();continue;}
in[vec[x].back().first]=true;now.push_back(vec[x].back());vec[x].pop_back();
}
while (!vec[y].empty())
{
if (in[vec[y].back().first]) {vec[y].pop_back();continue;}
in[vec[y].back().first]=true;now.push_back(vec[y].back());vec[y].pop_back();
}
reverse(now.begin(),now.end());
return now;
}
void upd (int x)
{
LL o=lzy[x];lzy[x]=0;
int siz=vec[x].size();
for (int i=0;i<siz;i++) {vec[x][i].first=find_fa(vec[x][i].first);vec[x][i].second-=o;}
}
int t[N],tim;
LL solve ()
{
ans=0;memset(t,0,sizeof(t));
while (true)
{
int cnt=0;
for (int u=1;u<=n;u++) vis[u]=0;
for (int u=1;u<=n;u++) if (fa[u]==u)
{
while (!vec[u].empty())
{
int x=vec[u].back().first;
if (find_fa(x)==find_fa(u)) vec[u].pop_back();
else break;
}
assert(!vec[u].empty());
mn[u]=vec[u].back().second-lzy[u];
par[u]=find_fa(vec[u].back().first);
ans=ans+mn[u];lzy[u]+=mn[u];
}
vis[0]=true;
bool tf=false;
for (int u=1;u<=n;u++) if (fa[u]==u&&vis[u]==false)
{
int i=u;
tim++;
while (!vis[i]) {vis[i]=true;t[i]=tim;i=par[i];}
if (t[i]==tim)//loop
{
tf=true;
int j=i;upd(j);
i=par[i];
while (i!=j)
{
fa[i]=find_fa(j);
upd(i);vec[j]=Merge(i,j);
i=par[i];
}
}
}
if (!tf) return ans;
}
}
}
O(1)LCA
点击查看代码
struct VTREE {
struct ST {
int n,m;
vector<int> key;
vector2D<int> st;
int lg(int x) {
return 31-__builtin_clz(x);
}
int merge(int x,int y) {
return (key[x]<key[y])? x: y;
}
void init(vector<int> &a, vector<int> &key_) {
n=isz(a); m=lg(n-1)+1; key=key_;
st.resize(m);
st[0]=a;
rep(i,1,m) st[i].resize(n-(1<<i)+1);
rep(i,1,m) loop(j,isz(st[i]))
st[i][j]=merge(st[i-1][j],st[i-1][j+(1<<(i-1))]);
}
int calc(int l,int r) {
int k=lg(r-l);
return merge(st[k][l],st[k][r-(1<<k)]);
}
} st;
struct edge {
int to; ll c;
};
int n,root;
vector<ll> len;
vector<vector<edge>> go;
vector<int> fa,sz,dep,lno,rno,pos;
vector<int> piv,vis;
void init(int n_,int root_) {
n=n_; root=root_;
pos.clear();
fa.assign(n,-1);
sz.assign(n,1);
go.assign(n,{});
dep.assign(n,0);
len.assign(n,0);
lno.assign(n,-1);
rno.assign(n,-1);
piv.assign(n,0);
vis.assign(n,0);
}
void read() {
int u,v;
loop(i,n-1) cin>>u>>v, add(u-1,v-1);
}
void add(int u,int v,ll w=1) {
go[u].push_back({v,w});
go[v].push_back({u,w});
}
void _dfs(int x) {
lno[x]=isz(pos);
pos.push_back(x);
for(auto &e: go[x]) if(e.to!=fa[x]) {
dep[e.to]=dep[x]+1;
len[e.to]=len[x]+e.c;
fa[e.to]=x;
_dfs(e.to);
sz[x]+=sz[e.to];
pos.push_back(x);
}
rno[x]=isz(pos);
}
int lca(int x,int y) {
x=lno[x]; y=lno[y];
if(x>y) swap(x,y);
return st.calc(x,y+1);
}
int dist(int x,int y) {
return len[x]+len[y]-2*len[lca(x,y)];
}
void build() {
_dfs(root);
st.init(pos,dep);
}
}a;
树上路径交:
点击查看代码
PI Merge (PI x,PI y)
{
if (x.first==-1) return x;
int w1=LCA(x.first,x.second);
int w2=LCA(y.first,y.second);
if (dep[w1]>dep[w2]) swap(w1,w2);
if (!in(w1,w2)) return {-1,-1};
int A=LCA(x.first,y.first),B=LCA(x.first,y.second);
int C=LCA(x.second,y.first),D=LCA(x.second,y.second);
int p=-1,q=-1;
if (in(w2,A)&&A!=w1)
{
if (p==-1) p=A;
else if (A!=p) q=A;
}
A=B;
if (in(w2,A)&&A!=w1)
{
if (p==-1) p=A;
else if (A!=p) q=A;
}
A=C;
if (in(w2,A)&&A!=w1)
{
if (p==-1) p=A;
else if (A!=p) q=A;
}
A=D;
if (in(w2,A)&&A!=w1)
{
if (p==-1) p=A;
else if (A!=p) q=A;
}
if (p==-1&&w1==w2) p=w1;
if (q==-1&&w1==w2) q=w2;
if (q==-1) q=p;
return {p,q};
}
原根:
点击查看代码
namespace priroot
{
int pri[105],cnt;
void div (LL n)
{
for (int u=2;u*u<=n;u++) if (n%u==0)
{
pri[++cnt]=u;
while (n%u==0) n/=u;
}
if (n) pri[++cnt]=n;
}
int pow (int x,int y,int MOD)
{
int now=1;while (y)
{
if (y&1) now=1ll*now*x%MOD;
y>>=1;x=1ll*x*x%MOD;
}
return now;
}
int solve (int n)
{
cnt=0;
for (int u=2;u*u<=n;u++) if (n%u==0) return -1;
div(n-1);
for (int u=2;;u++)
{
bool tf=true;
for (int i=1;i<=cnt;i++)
{
if (pow(u,(n-1)/pri[i],n)==1)
{tf=false;break;}
}
if (tf) return u;
}
}
}
点击查看代码
namespace math
{
bool vis[N];
int cnt=0,phi[N];
LL pre[N],pri[N];
int h[N];
void Init (int _n)
{
memset(vis,false,sizeof(vis));vis[1]=true;
for (int u=2;u<=_n;u++)
{
h[u]=h[u-1];
if (!vis[u]) {pri[++cnt]=u;phi[u]=phi[u-1];h[u]++;}
for (int i=1;i<=cnt;i++)
{
int j=pri[i];
if (j*u>_n) break;
vis[j*u]=true;
if (u%j==0) {phi[u*j]=phi[u]*j;break;}
phi[u*j]=phi[u]*phi[j];
}
}
for (int u=1;u<=cnt;u++) pre[u]=pre[u-1]+pri[u];
}
int n,P;
LL g[N],w[N];
int id[N],id1[N],m;
int get_id (LL x)
{
if (x<=P) return id[x];
return id1[n/x];
}
void solve (LL _n)
{
n=_n;P=sqrt(n);
Init(P);
for (LL l=1;l<=n;)
{
LL v=n/l,r=n/v;
if (v<=P) id[v]=++m; else id1[n/v]=++m;
w[m]=v;g[m]=(2+v)*(v-1)/2;
l=r+1;
}
for (int u=1;u<=cnt&&pri[u]<=P;u++)
{
for (int i=1;i<=m;i++)
{
if (pri[u]*pri[u]>w[i]) break;
g[i]=g[i]-pri[u]*(g[get_id(w[i]/pri[u])]-pre[u-1]);
}
}
}
}
点击查看代码
namespace qgcd
{
typedef long long LL;
const int N=1000000,sn=1000;
bool notprime[N+5];
int p[N+5],prime[N+5],cnt,split[N+5][3];
int g[sn+5][sn+5];
void init_gcd(){
notprime[1]=1;
int i,j,d;
for(i=2;i<N;i++){
if(!notprime[i]){
prime[++cnt]=i;
p[i]=i;
}
for(j=1;j<=cnt;j++){
if((LL)prime[j]*i>=N) break;
d=prime[j]*i;
notprime[d]=1;
p[d]=prime[j];
if(i%prime[j]==0) break;
}
}
split[1][0]=split[1][1]=split[1][2]=1;
for(i=2;i<N;i++){
memcpy(split[i],split[i/p[i]],sizeof(split[i/p[i]]));
if(split[i][0]*p[i]<=sn) split[i][0]*=p[i];
else if(split[i][1]*p[i]<=sn) split[i][1]*=p[i];
else split[i][2]*=p[i];
}
// gcd(0,0)=0 , gcd(0,x)=x
for(i=0;i<=sn;i++)
for(j=0;j<=i;j++){
if(!i||!j) g[i][j]=i|j;
else g[i][j]=g[j][i]=g[j][i%j];//j<=i
}
}
int gcd(int x,int y){
int ans=1,i,d;
for(i=0;i<3;i++){
if(split[x][i]<=sn) d=g[split[x][i]][y%split[x][i]];
else d=(y%split[x][i]==0)?split[x][i]:1;
ans*=d;
y/=d;//±ÜÃâËãÖØ
}
return ans;
}
}