模板整理
固定大小子集搜索
点击查看代码
using namespace std;
map<string,int> dic;
int g,a,n;
int v[11000],tot;
string name[11000];
void dfs(int st)
{
if (tot>=n)return;
if (st>a)return;
int flag=0;
for(int i=st+1;i<=a;i++)
if (v[st]^v[i])flag=1;
if (!flag)return;
dfs(st+1);
for(int i=st+1;i<=a;i++)
if (v[st]^v[i])
{
if (tot>=n)return;
int x=st;
int y=i;
if (!v[x])swap(x,y);
tot++;
cout<<name[x]<<" "<<name[y]<<endl;
v[x]=0;
v[y]=1;
dfs(st+1);
return;
}
}
int main()
{
int T;
cin>>T;
while (T--)
{
scanf("%d%d%d",&g,&n,&a);
n--;
dic.clear();
for(int i=1;i<=a;i++)
{
cin>>name[i];
dic[name[i]]=i;
}
for(int i=1;i<=a;i++)v[i]=0;
for(int i=1;i<=g;i++)
{
string s; cin>>s;
v[dic[s]]=1;
}
tot=0;
dfs(1);
if (T!=0)puts("");
}
return 0;
}
环搜索
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
vector<int> vec[N];
vector<int> h[N];
int fa[N];
int find_fa (int x) {return fa[x]==x?x:fa[x]=find_fa(fa[x]);}
bool flag[N];
vector<int> tmp[N];
void dfs (int x,int fa)
{
for (auto y:vec[x])
{
if (y==fa) continue;
dfs(y,x);
if (flag[y]) tmp[x].push_back(y);
else if (tmp[y].size()) tmp[x].push_back(tmp[y][0]);
}
if (flag[x]||tmp[x].size()>=2)
{
flag[x]=true;
for (auto y:tmp[x])
{
h[x].push_back(y);
h[y].push_back(x);
}
}
}
int ans=0;
bool vis[N];
bool in[N];
void dfs1 (int x,int fa,int tp)
{
in[x]=true;
for (auto y:h[x])
{
if (y==fa) fa=0;
else if (y==tp) ans++;
else if (!vis[y]&&!in[y]) dfs1(y,x,tp);
}
in[x]=false;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int u=1;u<=n;u++) fa[u]=u;
for (int u=1;u<=m;u++)
{
int x,y;
scanf("%d%d",&x,&y);
if (find_fa(x)!=find_fa(y))
{
vec[x].push_back(y);
vec[y].push_back(x);
fa[find_fa(x)]=y;
}
else
{
h[x].push_back(y);
h[y].push_back(x);
flag[x]=true;flag[y]=true;
}
}
dfs(1,0);
for (int u=1;u<=n;u++)
if (flag[u])
{
vis[u]=1;
dfs1(u,0,u);
}
printf("%d\n",ans/2);
return 0;
}
容斥路径
i步,从st走到1或n(其他类似),范围0~ed
复杂度i/ed
点击查看代码
int G(int i,int x,int y) {
if(x > y)swap(x,y);
if(i < y - x || (i + x - y) % 2)return 0;
return C(i,(i + x - y) / 2);
}
int L(int x,int n){return -x;}
int R(int x,int n){return 2 * (n + 1) - x;}
int f1,fn;
void calc (int i,int st,int ed)
{
f1 = G(i,st,1);fn = G(i,st,ed);
int l1 = st,r1 = st,ln = st,rn = st;
int ty = MOD - 1;
while(true)
{
int nl1 = L(r1,ed),nr1 = R(l1,ed),nln = L(rn,ed),nrn = R(ln,ed);
l1 = nl1;r1 = nr1;ln = nln;rn = nrn;
if(abs(1 - l1) > i && abs(r1 - 1) > i && abs(ed - ln) > i && abs(rn - ed) > i)break;
f1=add(f1,mul(ty,G(i,l1,1)));
f1=add(f1,mul(ty,G(i,r1,1)));
fn=add(fn,mul(ty,G(i,ln,ed)));
fn=add(fn,mul(ty,G(i,rn,ed)));
ty = MOD - ty;
}
}
fhq_treap
点击查看代码
#include <cstdio>
#include <cstdlib>
#include <ctime>
#define N 500005
using namespace std;
int inline read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int ch[N][2],val[N],pri[N],siz[N],sz;
void update(int x){siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];}
int new_node(int v)
{
siz[++sz]=1;
val[sz]=v;
pri[sz]=rand();
return sz;
}
int merge(int x,int y)
{
if (!x || !y) return x+y;
if (pri[x]<pri[y])
{
ch[x][1]=merge(ch[x][1],y);
update(x);
return x;
}
else
{
ch[y][0]=merge(x,ch[y][0]);
update(y);
return y;
}
}
void split(int now,int k,int &x,int &y)
{
if (!now) x=y=0;
else
{
if (val[now]<=k)
x=now,split(ch[now][1],k,ch[now][1],y);
else
y=now,split(ch[now][0],k,x,ch[now][0]);
update(now);
}
}
int kth(int now,int k)
{
while(1)
{
if (k<=siz[ch[now][0]])
now=ch[now][0];
else
if (k==siz[ch[now][0]]+1)
return now;
else
k-=siz[ch[now][0]]+1,now=ch[now][1];
}
}
int main()
{
srand((unsigned)time(NULL));
int T,com,x,y,z,a,b,root=0;
scanf("%d",&T);
while(T--)
{
com=read(),a=read();
if (com==1)
{
split(root,a,x,y);
root=merge(merge(x,new_node(a)),y);
}
else
if (com==2)
{
split(root,a,x,z);
split(x,a-1,x,y);
y=merge(ch[y][0],ch[y][1]);
root=merge(merge(x,y),z);
}
else
if (com==3)
{
split(root,a-1,x,y);
printf("%d\n",siz[x]+1);
root=merge(x,y);
}
else
if (com==4)
printf("%d\n",val[kth(root,a)]);
else
if (com==5)
{
split(root,a-1,x,y);
printf("%d\n",val[kth(x,siz[x])]);
root=merge(x,y);
}
else
{
split(root,a,x,y);
printf("%d\n",val[kth(y,1)]);
root=merge(x,y);
}
}
}
/*
1.插入 x 数
2.删除 x 数(若有多个相同的数,因只删除一个)
3.查询 x 数的排名(排名定义为比当前数小的数的个数 +1 )
4.查询排名为 x 的数
5.求 x 的前驱(前驱定义为小于 x,且最大的数)
6.求 x 的后继(后继定义为大于 x,且最小的数)*/
上取整分块
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int Up (int x,int y)
{
return (x+y-1)/y;
}
int main()
{
int n;
scanf("%d",&n);
printf("1 ");
for (int u=2;u<=n;u++) if (Up(n,u)!=Up(n,u-1)) printf("%d ",u);printf("\n");
int l=1,r=1;
while (l<=n)
{
int res=Up(n,l);
if (res==1) r=n;
else r=Up(n,res-1)-1;
printf("%d ",l);
l=r+1;
}
return 0;
}
LCT维护最小生成树
点击查看代码
struct LinkCutTree {
bool rev[N];
int fa[N],ch[N][2];
int val[N],mx[N];
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
#define dir(x) (x == ch[fa[x]][1])
#define IsRoot(x) (x != ch[fa[x]][0] && x != ch[fa[x]][1])
inline void PushUp(int x) {
mx[x] = x;
if(ls(x) && val[mx[ls(x)]] > val[mx[x]]) mx[x] = mx[ls(x)];
if(rs(x) && val[mx[rs(x)]] > val[mx[x]]) mx[x] = mx[rs(x)];
}
inline void PushDown(int x) {
if(rev[x]) {
if(ls(x)) std::swap(ls(ls(x)),rs(ls(x))),rev[ls(x)] ^= 1;
if(rs(x)) std::swap(ls(rs(x)),rs(rs(x))),rev[rs(x)] ^= 1;
rev[x] = 0;
}
}
void update(int x) {
if(!IsRoot(x)) update(fa[x]);
PushDown(x);
}
inline void rotate(int x) {
int y = fa[x],z = fa[y],d = dir(x),w = ch[x][d ^ 1];
if(!IsRoot(y)) ch[z][dir(y)] = x;
ch[y][d] = w,ch[x][d ^ 1] = y;
fa[y] = x,fa[x] = z;
if(w) fa[w] = y;
PushUp(y);
}
inline void splay(int x) {
update(x);
while(!IsRoot(x)) {
int y = fa[x],z = fa[y];
if(!IsRoot(y))
rotate((ls(y) == x) ^ (ls(z) == y) ? x : y);
rotate(x);
}
PushUp(x);
}
inline void access(int x) {
for(int p = 0;x;p = x,x = fa[x])
{
splay(x),rs(x) = p,PushUp(x);
}
}
inline void MakeRoot(int x) {
access(x),splay(x);
std::swap(ls(x),rs(x)),rev[x] ^= 1;
}
inline int FindRoot(int x) {
access(x),splay(x);
while(ls(x)) PushDown(x),x = ls(x);
splay(x);
return x;
}
inline void split(int x,int y) {
MakeRoot(x),access(y),splay(y);
}
inline void link(int x,int y) {
MakeRoot(x); fa[x] = y;
}
}T;
int ecnt=0,res=0;
int X[N],Y[N],W[N];
int n,m;
bool in[N];
void modify (int ep,int i)
{
int u,v,w;
u=X[i];v=Y[i];w=W[i];
T.MakeRoot(u);
T.split(u,v);
T.splay(ep);
T.fa[T.ch[ep][0]] = T.fa[T.ch[ep][1]] = 0;
T.ch[ep][0]=T.ch[ep][1]=0;
T.link(i + n,u);
T.link(i + n,v);
res -= T.val[ep];
res += w;
}
int link (int i)
{
int u,v,w;
u=X[i];v=Y[i];w=W[i];
if(u == v) return 0;
T.val[i + n] = w;
T.MakeRoot(u);
if(u != T.FindRoot(v)) {
T.link(i + n,u),T.link(i + n,v);
++ecnt;
res += w;
return 0;
}
else {
T.split(u,v);
int ep = T.mx[v];
if(w < T.val[ep]) {
modify(ep,i);
return ep-n;
}
}
return 0;
}
KD-Tree2 (分块重构) 来源:https://www.luogu.com.cn/blog/command-block/kdt-xiao-ji
点击查看代码
#include<algorithm>
#include<cstdio>
#define MaxN 100500
using namespace std;
int read(){}
struct Node
{int xl,yl,xr,yr,s;}a[MaxN<<2];
struct Point{int x,y,v;}p[MaxN];
bool cmpX(const Point &A,const Point &B)
{return A.x<B.x;}
bool cmpY(const Point &A,const Point &B)
{return A.y<B.y;}
void build(int l,int r,int u,bool kd)
{
if (l==r){
a[u].xl=a[u].xr=p[l].x;
a[u].yl=a[u].yr=p[l].y;
a[u].s=p[l].v;
return ;
}int mid=(l+r)>>1;
nth_element(p+l,p+mid,p+r+1,kd ? cmpX : cmpY);
build(l,mid,u<<1,!kd);
build(mid+1,r,u<<1|1,!kd);
int ls=u<<1,rs=u<<1|1;
a[u].s=a[ls].s+a[rs].s;
a[u].xl=min(a[ls].xl,a[rs].xl);
a[u].yl=min(a[ls].yl,a[rs].yl);
a[u].xr=max(a[ls].xr,a[rs].xr);
a[u].yr=max(a[ls].yr,a[rs].yr);
}
Node wf;
void qry(int u=1)
{
if (wf.xr<a[u].xl||a[u].xr<wf.xl||wf.yr<a[u].yl||a[u].yr<wf.yl)return ;
if (wf.xl<=a[u].xl&&a[u].xr<=wf.xr&&wf.yl<=a[u].yl&&a[u].yr<=wf.yr)
{wf.s+=a[u].s;return ;}
qry(u<<1|1);qry(u<<1);
}
int main()
{
int pl=0,pr=0,n=read(),las=0;
while(1){
int op=read();
if (op==1){
pr++;
p[pr].x=read()^las;
p[pr].y=read()^las;
p[pr].v=read()^las;
if ((pr-pl)*(pr-pl)>pr*40)build(1,pl=pr,1,0);
}if (op==2){
wf.xl=read()^las;wf.yl=read()^las;
wf.xr=read()^las;wf.yr=read()^las;
wf.s=0;qry();
for (int i=pl+1;i<=pr;i++)
if (wf.xl<=p[i].x&&p[i].x<=wf.xr&&wf.yl<=p[i].y&&p[i].y<=wf.yr)
wf.s+=p[i].v;
printf("%d\n",las=wf.s);
}if (op==3)break;
}return 0;
}
KD-Tree1 (替罪羊重构)
点击查看代码
#include<algorithm>
#include<cstdio>
#define MaxN 200500
using namespace std;
int read(){}
struct Point{int x,y,v;}p[MaxN];
int tot;
bool cmpX(const Point &A,const Point &B)
{return A.x<B.x;}
bool cmpY(const Point &A,const Point &B)
{return A.y<B.y;}
struct Node{
int xl,yl,xr,yr,l,r,s,c;
void leaf(Point &P){
xl=xr=P.x;yl=yr=P.y;
s=P.v;c=1;
}
}a[MaxN<<1];
int tn,rt,rub[MaxN<<1],tb;
int cre(){
if (!tb)return ++tn;
int u=rub[tb--];
a[u]=(Node){0,0,0,0,0,0};
return u;
}
void pia(int u)
{
if (a[u].l==a[u].r){
p[++tot]=(Point){a[u].xl,a[u].yl,a[u].s};
rub[++tb]=u;return ;
}pia(a[u].l);pia(a[u].r);
rub[++tb]=u;
}
bool chk(int u)
{return a[u].c>3&&max(a[a[u].l].c,a[a[u].r].c)*5>a[u].c*3;}
inline void up(int u)
{
int l=a[u].l,r=a[u].r;
a[u].s=a[l].s+a[r].s;
a[u].c=a[l].c+a[r].c;
a[u].xl=min(a[l].xl,a[r].xl);
a[u].yl=min(a[l].yl,a[r].yl);
a[u].xr=max(a[l].xr,a[r].xr);
a[u].yr=max(a[l].yr,a[r].yr);
}
void build(int l,int r,int &u,bool kd)
{
u=cre();
if (l==r){a[u].leaf(p[l]);return ;}
int mid=(l+r)>>1;
nth_element(p+l,p+mid,p+r+1,kd ? cmpX : cmpY);
build(l,mid,a[u].l,!kd);
build(mid+1,r,a[u].r,!kd);
up(u);
}
Point wfp,reb;
void ins(int u,bool kd)
{
if (a[u].l==a[u].r){
int v0=cre(),v1=cre();
a[v0]=a[u];a[v1].leaf(wfp);
a[u].l=v0;a[u].r=v1;up(u);
return ;
}int ls=a[u].l;
if (a[ls].xl<=wfp.x&&wfp.x<=a[ls].xr
&&a[ls].yl<=wfp.y&&wfp.y<=a[ls].yr)
ins(ls,!kd);
else ins(a[u].r,!kd);
up(u);
if (chk(u)){reb.x=u;reb.y=kd;}
}
void insert()
{
if (!tn){a[tn=1].leaf(wfp);return ;}
reb.x=0;ins(1,0);
if (reb.x){
tot=0;pia(reb.x);
int tmp;build(1,tot,tmp,reb.y);
}
}
Node wf;
void qry(int u=1)
{
if (wf.xr<a[u].xl||a[u].xr<wf.xl||wf.yr<a[u].yl|a[u].yr<wf.yl)return ;
if (wf.xl<=a[u].xl&&a[u].xr<=wf.xr&&wf.yl<=a[u].yl&&a[u].yr<=wf.yr)
{wf.s+=a[u].s;return ;}
qry(a[u].l);qry(a[u].r);
}
int n,las;
int main()
{
while(1){
int op=read();
if (op==1){
wfp.x=read()^las;
wfp.y=read()^las;
wfp.v=read()^las;
insert();
}if (op==2){
wf.xl=read()^las;wf.yl=read()^las;
wf.xr=read()^las;wf.yr=read()^las;
wf.s=0;qry();
printf("%d\n",las=wf.s);
}if (op==3)break;
}return 0;
}
动态分配id
点击查看代码
#include <bits/stdc++.h>
#define maxn 500086
using namespace std;
typedef long long ll;
#define ls(x) (t[x].son[0])
#define rs(x) (t[x].son[1])
ll val[maxn];
int nxt[maxn], ed[maxn];
namespace ScapegoatTree{
struct Node{
int son[2], siz;
}t[maxn];
inline void up(int x){
t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
}
const double k = 0.725;
inline bool bad(int x){
return k * t[x].siz <= max(t[ls(x)].siz, t[rs(x)].siz);
}
int a[maxn], tot;
int build(int l, int r, ll L, ll R){
int mid = l + r >> 1, x = a[mid];
val[x] = L + R >> 1;
if(l < mid) ls(x) = build(l, mid - 1, L, val[x] - 1);
if(mid < r) rs(x) = build(mid + 1, r, val[x] + 1, R);
return up(x), x;
}
void dfs(int x){
if(ls(x)) dfs(ls(x)), ls(x) = 0;
a[++tot] = x;
if(rs(x)) dfs(rs(x)), rs(x) = 0;
}
inline void rebuild(int &x, ll l, ll r){
tot = 0, dfs(x);
x = build(1, tot, l, r);
}
void insert(int &x, int y, ll l, ll r){
if(!x){
x = y, ls(x) = rs(x) = 0, t[x].siz = 1;
return;
}
if(val[y] < val[x]) insert(ls(x), y, l, val[x] - 1);
else insert(rs(x), y, val[x] + 1, r);
up(x);
if(bad(x)) rebuild(x, l, r);
}
}
namespace FHQTreap{
struct Node{
int son[2], pri, siz;
}t[maxn];
int rt[maxn];
vector<int> v;
int a, b, c, d;
inline int rand(){
static int seed = 123456;
return seed = seed * 482711ll % 2147483647;
}
inline void up(int x){
t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
}
void split(int x, ll Val, int &a, int &b){
if(!x) return (void)(a = b = 0);
if(val[x] <= Val) a = x, split(rs(x), Val, rs(x), b);
else b = x, split(ls(x), Val, a, ls(x));
up(x);
}
int merge(int x, int y){
if(!x || !y) return x | y;
if(t[x].pri > t[y].pri) return rs(x) = merge(rs(x), y), up(x), x;
return ls(y) = merge(x, ls(y)), up(y), y;
}
inline void insert(int id, int x){
ls(x) = rs(x) = 0, t[x].siz = 1;
t[x].pri = rand();
v.push_back(id);
split(rt[id], val[x], a, b);
rt[id] = merge(a, merge(x, b));
}
inline int query(int id, ll x){
split(rt[id], x, a, b);
int ans = t[a].siz;
rt[id] = merge(a, b);
return ans;
}
inline void clear(){
while(!v.empty()) rt[v.back()] = 0, v.pop_back();
}
}
int t, n, m;
int ans;
int opt, x, y;
int rt;
int main(){
scanf("%d", &t);
val[0] = (1ll << 62) - 1;
while(t--){
scanf("%d%d", &y, &m), n = 1, rt = 0;
val[n] = nxt[n] = ed[n] = ans = 0;
ScapegoatTree::insert(rt, n, val[n], val[nxt[n]]);
FHQTreap::insert(y, n);
while(m--){
scanf("%d%d%d", &opt, &x, &y);
opt ^= ans, x ^= ans, y ^= ans;
if(opt == 1){
n++, ed[n] = nxt[n] = nxt[x], val[n] = val[x] + val[nxt[x]] >> 1;
ScapegoatTree::insert(rt, n, val[1], val[0]);
FHQTreap::insert(y, n);
nxt[x] = n;
}else{
printf("%d\n", ans = FHQTreap::query(y, val[ed[x]] - 1) - FHQTreap::query(y, val[x] - 1));
}
}
FHQTreap::clear();
}
}
虚树:
点击查看代码
namespace VT{
int ti; //时间戳
int ts[maxn];
int vis[maxn];
int depth[maxn];
int dfn[maxn];
void dfs(int u, int fa = -1)
{
vis[u]=1;
dfn[u] = ++ti; //dfs序
ts[ti] = u; //括号序列时间戳映射
for (auto v:G[u])
{
if (vis[v])
continue;
depth[v] = depth[u] + 1;
dfs(v, u);
ts[++ti] = u;
}
}
int ST[maxn][22]; //LCA转RMQ用ST表求
bool cmp(int x, int y) { return depth[x] < depth[y]; }
void RMQ()
{
for (int i = 1; i <= ti; i++)
ST[i][0] = ts[i];
for (int j = 1; (1 << j) <= ti; j++)
{
for (int i = 1; i + (1 << (j - 1)) - 1 <= ti; i++)
{
if (cmp(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]))
ST[i][j] = ST[i][j - 1];
else
ST[i][j] = ST[i + (1 << (j - 1))][j - 1];
}
}
}
int LCA(int u, int v)
{
int l = dfn[u], r = dfn[v];
if (l > r)
swap(l, r);
int k = 31 - __builtin_clz(r - l + 1);
if (cmp(ST[l][k], ST[r - (1 << k) + 1][k]))
return ST[l][k];
return ST[r - (1 << k) + 1][k];
}
inline void access(int u,int v,int id=0)
{
g[u].emplace_back(v,id);
g[v].emplace_back(u,id);
//cout<<u<<"----"<<v<<":"<<id<<endl;
}
void Virtual(vector<int> &all) //关键点
{
static int st[maxn]; //栈模拟访问
int top = 0;
sort(all.begin(), all.end(), [&](int i,int j){return dfn[i] < dfn[j];});
for (auto &u : all)
{
if (top == 0)
st[++top] = u;
else
{
int lca = LCA(st[top], u);
while (top > 1 && dfn[st[top - 1]] >= dfn[lca])
{ //栈中至少有两个元素,则开始向上连边
access(st[top],st[top-1]);
top--;
}
if (lca != st[top]) //最后将lca也放进去
{
access(st[top], lca);
st[top] = lca;
}
st[++top] = u;
}
}
while (top > 1) //所有元素出栈
{
access(st[top], st[top - 1]);
--top;
}
}
};
KM:
点击查看代码
namespace KM
{
#define I inline int
#define V inline void
#define FOR(i,a,b) for(int i=a;i<=b;i++)
const int N=5e2+1,INF=0x3f3f3f3f;
int ans;
int nl,nr,m,sl[N],pre[N],e[N][N];
int lx[N],ly[N],vx[N],vy[N],mx[N],my[N];
V link(int x,int y){mx[x]=y,my[y]=x;}
I cmin(int&x,int y){return(y-x>>31)&&(x=y,1);}
V upd(int u){FOR(v,1,nr)if(!vy[v]&&cmin(sl[v],lx[u]+ly[v]-e[u][v]))pre[v]=u;}
V add(int x){
FOR(i,1,nl)if(vx[i])lx[i]-=x;
FOR(i,1,nr)vy[i]?ly[i]+=x:sl[i]-=x;
}
I find(int x=0){FOR(i,1,nr)if(!vy[i]&&sl[i]<sl[x])x=i;return x;}
V once(){
FOR(i,0,nr)vy[i]=0,sl[i]=INF;
FOR(i,1,nl)if(vx[i]=!mx[i])upd(i);
for(int u,v;add(sl[v=find()]),u=my[v];)vx[u]=vy[v]=1,upd(u);
for(int u,v=find(),p;u=pre[v],v;v=p)p=mx[u],link(u,v);
}
void Init(int _nl,int _nr){
nl=_nl;nr=_nr;
// printf("Init:%d %d\n",nl,nr);
for (int u=1;u<=nl;u++)
for (int i=1;i<=nr;i++)
e[u][i]=0;
}
int solve()
{
FOR(i,1,nl)lx[i]=INF;
int t=max(nl,nr);
FOR(i,0,t) mx[i]=sl[i]=pre[i]=vx[i]=ly[i]=vy[i]=my[i]=0;
FOR(i,1,nl)once();
ans=0;
FOR(i,1,nl) ans+=e[i][mx[i]];
return ans;
}
void link (int x,int y,int w)
{
e[x][y]=w;
}
}
大整数分解
点击查看代码
LL gcd(LL x,LL y)
{
if(!y)
return x;
return gcd(y,x%y);
}
inline long long mul(long long x,long long y,long long mod){
long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
if(tmp>=mod)tmp-=mod;
return tmp<0?tmp+mod:tmp;
}
LL fexp(LL x,LL t,LL M){
if(!t)return 1;
LL tmp=fexp(x,t>>1,M);tmp=mul(tmp,tmp,M);
return (t&1)?mul(tmp,x,M):tmp;
}
LL p[355],A[8]={2,3,7,13,31,998244353,1000000007,1000000009};
int cnt=0;
bool bx2k(LL n){
if(n==2)return 1;
if(n<2||n%2==0)return 0;
LL m=n-1;
while((~m)&1)m>>=1;
for(int i=0;i<6&&A[i]<n;i++){
LL a=A[i],x=fexp(a,m,n),y=0;
for(LL j=m<<1;j<n;j<<=1){
y=mul(x,x,n);
if(y==1)if(x!=1&&x!=n-1)return 0;else break;
x=y;
}
if(y!=1)return 0;
}
return 1;
}
LL czy(LL n,LL c){
LL x=rand()%(n-1)+1,y=x,now=1,lst=2;
while(1){
now++;x=(mul(x,x,n)+c)%n;
LL p=gcd(y-x+n,n);
if(y==x)return n;
if(p>1&&p<n)return p;
if(now==lst){
y=x;lst<<=1;
}
}
}
bool f;
vector<LL> vec;
void find(LL n){
if(n==1)return;
if(bx2k(n)){
vec.push_back(n);
// p[cnt++]=n;
return;
}
LL p=n;LL c=1;
while(p==n)p=czy(p,c++);
if(f)return;
find(p);find(n/p);
}
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;
}
}
}
树上路径交:
点击查看代码
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 isprime[mxm];
LL prime[mxm],w[mxm],id1[mxm],id2[mxm];
LL num_pri=0;
int h[mxm];
LL m=0;
LL sump[mxm];
__int128 g[mxm];
__int128 cal(LL x){
return (__int128)x*(x+1)/2-1;
}
LL n,mod;
LL sqr;
LL id3(LL x){
return x<=sqr?id1[x]:id2[n/x];
}
LL f(int x){
return 1;
}
void el(){
sqr=sqrt(N);
isprime[1]=1;
for(LL i=2;i<=sqr;++i){
h[i]=h[i-1];
if(!isprime[i]) prime[++num_pri]=i,sump[num_pri]=sump[num_pri-1]+f(prime[num_pri]),h[i]++;
for(LL j=1;j<=num_pri&&i*prime[j]<=sqr;++j){
isprime[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}//线性筛预处理 筛出素数 和 f(素数)的前缀和
}//正常
void init(){
for(LL i=1;i<=n;i=n/(n/i)+1){
w[++m]=n/i;
if(w[m]<=sqr){
id1[w[m]]=m;
}
else{
id2[n/w[m]]=m;
}//记录id
//g[m]=w[m]*(w[m]+1)/2-1;//初始化g
g[m]=w[m]-1;//2到w[m]所有f(x)的和
}
for(LL i = 1;i<=num_pri;++i){
for(LL j=1; j<=m && 1ll*prime[i]*prime[i] <= w[j]; ++j){
g[j]=g[j] - (__int128) f(prime[i])* (g[id3(w[j] / prime[i])] - sump[i - 1]);
}
}
}
LL calc (LL x)
{
return g[id3(x)] ;
}
}
点击查看代码
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;
}
}