模板整理

固定大小子集搜索

点击查看代码
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)] ;
	}
}
O(1)gcd
点击查看代码
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;
	}
}
posted @ 2021-09-27 09:19  Als123  阅读(59)  评论(0编辑  收藏  举报