NOIP前的一些计划

一些想法

距离NOIP2018只剩下一个星期的时间了,通过这几天在长郡的考试,渐渐感觉还有好多东西自己还不够熟练,也有些东西到现在还不会,现将NOIP前的一些计划列在这里,希望能在考前把他们全部完成吧

一些模板

这里是NOIP可能会考的数据结构和算法的模板

字符串算法:

(kmp)

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6+100;
int n,m,nex[maxn],k,ok[maxn];
char a[maxn],b[maxn];
void getnex(){
	nex[1]=0,k=0;
	for(int i=2;i<=m;i++){
		while(k&&b[i]!=b[k+1])
			k=nex[k];
		if(b[i]==b[k+1])
			k++;
		nex[i]=k;
	}
}
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%s%s",a+1,b+1);
	n=strlen(a+1),m=strlen(b+1);
	getnex();
	for(int i=0,j=0;i<=n;i++){
		while(j&&a[i+1]!=b[j+1])
			j=nex[j];
		if(a[i+1]==b[j+1])
			j++;
		if(j==m){
			ok[i+2-m]=1;
			j=nex[j];
		}
	}
	for(int i=1;i<=n;i++)
		if(ok[i])
			printf("%d
",i);
	for(int i=1;i<=m;i++)
		printf("%d ",nex[i]);
	printf("
");
	return 0;
}

(manacher)

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=3e7+100;
int p,r,a[maxn],ans,len;
char s[maxn],c[maxn];
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%s",s+1);
	len=strlen(s+1);
	for(int i=1;i<=len;i++)
		c[i*2]=s[i],
		c[i*2-1]='#';
	len=len*2+1;
	c[len]='#';
	c[0]='%';
	for(int i=1;i<=len;i++){
		if(i<r)
			a[i]=min(r-i,p*2-i);
		else
			a[i]=1;
		while(c[i-a[i]]==c[i+a[i]])
			a[i]++;
		if(a[i]+i>r)
			r=i+a[i],p=i;
		ans=max(ans,a[i]);
	}
	printf("%d
",ans-1);
	return 0;
}

(AC)自动机

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6+100,maxm=1e5+100;
struct AC{
	struct node{
		int fail,poi,son[26];
	};
	node d[maxm];
	int cnt;
	queue<int>q;
	void clean(int x){
		memset(d[x].son,0,sizeof(d[x].son));
		d[x].fail=0;
		d[x].poi=0;
	}
	void insert(char *s,int bh){
		int len=strlen(s),now=0;
		for(int i=0;i<len;i++){
			int y=s[i]-'a';
			if(!d[now].son[y]){
				d[now].son[y]=++cnt;
				clean(cnt);
			}
			now=d[now].son[y];
		}
		d[now].poi=bh;
	}
	void build(){
		for(int i=0;i<26;i++)
			if(d[0].son[i])
				d[d[0].son[i]].fail=0,
				q.push(d[0].son[i]);
		while(!q.empty()){
			int x=q.front();
			q.pop();
			for(int i=0;i<26;i++)
				if(d[x].son[i])
					d[d[x].son[i]].fail=d[d[x].fail].son[i],
					q.push(d[x].son[i]);
				else
					d[x].son[i]=d[d[x].fail].son[i];
		}
	}
	void query(char *s,int *ans){
		int len=strlen(s),now=0;
		for(int i=0;i<len;i++){
			now=d[now].son[s[i]-'a'];
			for(int i=now;i;i=d[i].fail)
				ans[d[i].poi]++;
		}
	}
};
AC g;
int n,len,ans[300],tot;
char a[maxn],b[300][80];
void clean(){
	memset(ans,0,sizeof(ans));
	tot=0;
	g.cnt=0;
	g.clean(0);
}
int main(){
//	freopen("2333.in","r",stdin);
	//freopen(".out","w",stdout);
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		clean();
		for(int i=1;i<=n;i++){
			scanf("%s",a);
			g.insert(a,++tot);
			memcpy(b[tot],a,sizeof(a));
		}
		g.build();
		scanf("%s",a);
		g.query(a,ans);
		int Ans=0;
		for(int i=1;i<=tot;i++)
			Ans=max(Ans,ans[i]);
		printf("%d
",Ans);
		for(int i=1;i<=tot;i++)
			if(Ans==ans[i])
				printf("%s
",b[i]);
	}
	return 0;
}

回文自动机

struct prt{
	node d[maxn];
	int lim,len,last,cnt;
	int getfail(int x,char *s){
		while(s[lim-d[x].len-1]!=s[lim])
			x=d[x].fail;
		return x;
	}
	void extend(int x,char *s){
		int cur=getfail(last,s);
		int now=d[cur].son[x];
		if(!now){
			now=++cnt;
			d[now].fail=d[getfail(d[cur].fail,s)].son[x];
			d[now].len=d[cur].len+2;
			d[cur].son[x]=now;
		}
		d[now].siz++;
		last=now;
	}
	void build(char *s){
		d[1].len=-1;
		d[0].fail=d[1].fail=1;
		cnt=last=1;
		len=strlen(s);
		for(lim=0;lim<len;lim++)
			extend(s[lim]-'a',s);
		for(int i=cnt;i>=2;i--)
			d[d[i].fail].siz+=d[i].siz,d[d[i].fail].siz%=P;
	}
};
prt g;

后缀自动机

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2e6+100;
struct SAM{
	struct node{
		int len,siz,link,son[26];
	};
	node d[maxn];
	int last,f,g,p,clo,cnt,c[maxn],a[maxn];
	void clone(int x,int y,int z){
		memcpy(d[x].son,d[y].son,sizeof(d[y].son));
		d[x].link=d[y].link;
		d[x].len=d[z].len+1;
	}
	void extend(int x){
		f=++cnt;
		d[f].len=d[last].len+1;
		d[f].siz++;
		g=last;
		last=f;
		while(~g&&!d[g].son[x])
			d[g].son[x]=f,g=d[g].link;
		if(g==-1){
			d[f].link=0;
			return;
		}
		p=d[g].son[x];
		if(d[p].len==d[g].len+1){
			d[f].link=p;
			return;
		}
		clo=++cnt;
		clone(clo,p,g);
		d[f].link=d[p].link=clo;
		while(~g&&d[g].son[x]==p)
			d[g].son[x]=clo,g=d[g].link;
	}
	void build(char *s){
		d[0].link=-1;
		int len=strlen(s);
		for(int i=0;i<len;i++)
			extend(s[i]-'a');
	}
	int query(int len){
		for(int i=1;i<=cnt;i++) c[d[i].len]++;
		for(int i=1;i<=len;i++) c[i]+=c[i-1];
		for(int i=cnt;i>=1;i--) a[c[d[i].len]--]=i;
		int ans=0;
		for(int i=cnt;i>=1;i--){
			d[d[a[i]].link].siz+=d[a[i]].siz; 
			if(d[a[i]].siz>1)
				ans=max(ans,d[a[i]].siz*d[a[i]].len);
		}
		return ans;
	}
};
SAM g;
char a[maxn];
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%s",a);
	g.build(a);
	printf("%d
",g.query(strlen(a)));
	return 0;
}

字符串(hash)

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
	int ans=0,fh=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			fh=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
	return ans*fh;
}
typedef unsigned long long ull;
const int maxn=1e4+100;
const ull base=131;
struct hash{
	inline ull gethash(char *s){
		ull ans=0;
		for(int i=0,L=strlen(s);i<L;i++)
			ans=(ans*base+s[i]);
		return ans;
	}
};
hash h;
int n;
ull a[maxn];
char s[maxn];
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%s",s),a[i]=h.gethash(s);
	sort(a+1,a+n+1);
	int ans=0;
	for(int i=1;i<=n;i++)
		if(a[i]!=a[i-1])
			ans++;
	printf("%d
",ans);
	return 0;
}

图论算法

缩点

#include<map>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
	int ans=0,fh=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			fh=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
	return ans*fh;
}
typedef long long ll;
const int maxn=1e4+100,maxm=1e5+100;
queue<int>q;
struct grafh{
	int u[maxm],v[maxm],nex[maxm],head[maxn],num;
	void add(int x,int y){
		v[++num]=y;
		u[num]=x;
		nex[num]=head[x];
		head[x]=num;
	}
}g,f;
int n,m,a,b,c[maxn],ans,p[maxn],sccno[maxn],scc_tot,siz[maxn],low[maxn],dfn[maxn],tim;
int du[maxn];
stack<int>st;
void tarjan(int x){
	dfn[x]=low[x]=++tim;
	st.push(x);
	for(int i=g.head[x];i;i=g.nex[i]){
		int y=g.v[i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else
			if(!sccno[y])
				low[x]=min(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		scc_tot++;
		while(1){
			int y=st.top();
			st.pop();
			sccno[y]=scc_tot;
			siz[scc_tot]+=c[y];
			if(y==x) break;
		}
	}
}
void rebuild(){
	for(int i=1;i<=n;i++){
		int x=sccno[i];
		for(int j=g.head[i];j;j=g.nex[j]){
			int y=sccno[g.v[j]];
			if(x!=y)
				f.add(x,y),du[y]++;
		}
	}
	n=scc_tot;
}
void work(){
	for(int i=1;i<=n;i++)
		if(!du[i])
			q.push(i);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		ans=max(ans,p[x]+siz[x]);
		for(int i=f.head[x];i;i=f.nex[i]){
			int y=f.v[i];
			p[y]=max(p[y],p[x]+siz[x]);
			du[y]--;
			if(!du[y]) q.push(y);
		}
	}
	printf("%d
",ans);
}
int main(){
	//freopen(".out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&c[i]);
	for(int i=1;i<=m;i++)
		scanf("%d%d",&a,&b),g.add(a,b);
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			tarjan(i);
	rebuild();
	work();
	return 0;
}

点双

边双

最小生成树

网络流

费用流

欧拉回路

混合图欧拉路

数论算法

exgcd

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	else{
		int z=exgcd(b,a%b,y,x);
		y-=a/b*x;
		return z;
	}
}

中国剩余定理

void crt(){
	for(int i=1;i<=n;i++) lcm=lcm*p[i];
	for(int i=1;i<=n;i++){
		ll x=lcm/p[i];
		ll y=poww(x,p[i]-2,p[i]);
		ans=(ans+y*x%lcm*a[i]%lcm)%lcm;
	}
	printf("%lld
",ans);
}
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
	int ans=0,fh=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			fh=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
	return ans*fh;
}
typedef long long ll;
const int maxn=1e6+100;
int n;
ll m[maxn],c[maxn];
inline ll C(ll a,ll b,ll p){
	ll c=a*b-(ll)((long double)a*b/p+0.5)*p;
	return c<0?c+p:c;
}
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	ll r=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return r;
}
inline ll inv(ll a,ll b){
	ll x,y;
	ll r=exgcd(a,b,x,y);
	while(x<0) x+=b;
	return x;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&m[i],&c[i]);
	bool err=0;
	for(int i=2;i<=n;i++){
		if(i==14)
			i=14;
		ll m1=m[i-1],m2=m[i],c1=c[i-1],c2=c[i],t=gcd(m1,m2);
		if((c2-c1)%t!=0){
			err=1;
			break;
		}
		m[i]=m1/t*m2;
		c[i]=C(C(inv(m1/t,m2/t),(c2-c1),m[i])/t%(m2/t),m1,m[i])+c1;
		c[i]=(c[i]%m[i]+m[i])%m[i];
	}
	if(!err) printf("%lld
",c[n]);
	else printf("-1
");
	return 0;
}

线性求逆元

void getinv(){
	inv[1]=1;
	for(int i=2;i<=n;i++)
		inv[i]=1ll*(p-p/i)*inv[p%i]%p;
}

Lucas定理

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
	int ans=0,fh=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			fh=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
	return ans*fh;
}
typedef long long ll;
const int maxn=1e6+100;
ll jc[maxn],n,m,p;
void ycl(){
	jc[0]=1;
	for(ll i=1;i<=p;i++)
		jc[i]=jc[i-1]*i%p;
}
inline ll poww(ll x,ll y){
	ll base=1;
	while(y){
		if(y&1) base=base*x%p;
		x=x*x%p;
		y>>=1;
	}
	return base;
}
inline ll C(ll x,ll y){
	if(x>y) return 0;
	return jc[y]*poww(jc[x],p-2)%p*poww(jc[y-x],p-2)%p;
}
ll lucas(ll x,ll y){
	if(x==0) return 1;
	return C(x%p,y%p)*lucas(x/p,y/p)%p;
}
int main(){
	int t=read();
	while(t--){
		scanf("%lld%lld%lld",&n,&m,&p);
		ycl();
		printf("%lld
",lucas(n,n+m));
	}
	return 0;
}

欧拉筛

void Euler(){
	vis[1]=1;
	for(int i=2;i<=maxn-1;i++){
		if(!vis[i])
			p[++num]=i;
		for(int j=1;j<=num&&p[j]*i<=maxn-1;j++){
			vis[p[j]*i]=1;
			if(i%p[j]==0) break;
		}
	}
}

数据结构

Splay

#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
	int ans=0,fh=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			fh=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
		ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
	return ans*fh;
}
typedef long long ll;
struct Splay{
	struct node{
		int poi,lazy,siz;
		node *son[2],*fa;
		node(){
			son[0]=son[1]=fa=NULL;
			siz=1;
			lazy=0;
		}
	}*root,*bj;
	inline int query(node *x){
		return x==NULL?0:x->siz;
	}
	inline int son(node *x){
		return x->fa==NULL?0:x==x->fa->son[1];
	}
	void updata(node *x){
		x->siz=x->son[0]==NULL?1:x->son[0]->siz+1;
		x->siz+=x->son[1]==NULL?0:x->son[1]->siz;
	}
	void revise(node *x){
		if(x==NULL) return;
		x->lazy^=1;
		swap(x->son[0],x->son[1]);
	}
	void pushdown(node *x){
		if(!x->lazy) return;
		x->lazy^=1;
		revise(x->son[0]);
		revise(x->son[1]);
	}
	void rotate(node *x){
		node *f=x->fa;
		node *g=f->fa;
		int a=son(x),b=son(f);
		f->son[a]=x->son[a^1];
		if(x->son[a^1]!=NULL)
			x->son[a^1]->fa=f;
		x->son[a^1]=f;
		f->fa=x;
		x->fa=g;
		if(g) g->son[b]=x;
		else root=x;
		updata(f),updata(x);
	}
	void splay(node *x,node *y){
		while(x->fa!=y){
			node *f=x->fa;
			node *g=f->fa;
			if(g!=y)
				rotate(son(x)==son(f)?f:x);
			rotate(x);
		}
	}
	void insert(int k,int p,node *x){
		int siz=query(x->son[0]);
		if(siz+1==k){
			int a=1;
			node *f=x;
			x=f->son[1];
			while(x!=NULL)
				f=x,x=f->son[0],a=0;
			x=new node();
			x->fa=f;
			x->poi=p;
			f->son[a]=x;
			splay(x,NULL);
			return;
		}
		if(siz+1>k) insert(k,p,x->son[0]);
		else insert(k-siz-1,p,x->son[1]);
	}
	void access(int k,node *y,node *x){
		pushdown(x);
		int siz=query(x->son[0]);
		if(siz+1==k){
			splay(x,y);
			bj=x;
			return;
		}
		if(siz+1>k) access(k,y,x->son[0]);
		else access(k-siz-1,y,x->son[1]);
	}
	void work(int l,int r){
		access(l,NULL,root);
		access(r+2,bj,root);
		revise(root->son[1]->son[0]);
	}
	void print(node *x){
		pushdown(x);
		if(x->son[0]!=NULL) print(x->son[0]);
		if(x->poi>0) printf("%d ",x->poi);
		if(x->son[1]!=NULL) print(x->son[1]);
	}
	Splay(){
		root=new node();
		root->poi=-233;
		insert(1,-666,root);
	}
	void ycl(int x){
		for(int i=1;i<=x;i++)
			insert(i,i,root);
	}
}zhy;
int n,m,l,r;
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%d%d",&n,&m);
	zhy.ycl(n);
	while(m--){
		scanf("%d%d",&l,&r);
		zhy.work(l,r);
	}
	zhy.print(zhy.root);
	printf("
");
	return 0;
}

主席树

#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
struct node{
    int siz,l,r;
};
struct nod{
    int l,r,bh,ans,k;
};
nod p[maxn];
node tre[maxn*30];
int n,m,z[maxn],num,tot,b[maxn],root[maxn],a[maxn];
map<int,bool>cz;
map<int,int>c;
bool cmp(nod x,nod y){
    return x.r<y.r;
}
bool Cmp(nod x,nod y){
    return x.bh<y.bh;
}
void build(int l,int r,int &now){
	now=++tot;
	if(l==r) return;
	int mid=l+r>>1;
	build(l,mid,tre[now].l);
	build(mid+1,r,tre[now].r); 
}
void insert(int x,int old,int &now,int l,int r){
	now=++tot;
	tre[now]=tre[old];
	tre[now].siz++;
	if(l==r) return;
	int mid=l+r>>1;
	if(x<=mid) insert(x,tre[old].l,tre[now].l,l,mid);
	else insert(x,tre[old].r,tre[now].r,mid+1,r);
}
int query(int k,int l,int r,int old,int now){
	if(l==r) return l;
	int siz=tre[tre[now].l].siz-tre[tre[old].l].siz,mid=(l+r)>>1;
	if(k<=siz) return query(k,l,mid,tre[old].l,tre[now].l);
	return query(k-siz,mid+1,r,tre[old].r,tre[now].r);
}
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(!cz[a[i]]){
            cz[a[i]]=1;
            b[++num]=a[i];
        }
    }
    sort(b+1,b+num+1);
    for(int i=1;i<=num;i++)
        c[b[i]]=i,z[i]=b[i];
    for(int i=1;i<=n;i++)
        a[i]=c[a[i]];
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].k),p[i].bh=i;
    sort(p+1,p+m+1,cmp);
    build(1,num,root[0]);
    int now=0;
    for(int i=1;i<=n;i++){
        insert(a[i],root[i-1],root[i],1,num);
        while(now<m&&p[now+1].r==i)
            now++,p[now].ans=query(p[now].k,1,num,root[p[now].l-1],root[i]);
    }
    sort(p+1,p+m+1,Cmp);
    for(int i=1;i<=m;i++)   
        printf("%d
",z[p[i].ans]); 
    return 0;
}

LCT

st表

一些知识点

容斥原理

博弈论

各种DP

一些计划

整理好上面的模板

luogu刷题满300道(然而咕掉了)

原文地址:https://www.cnblogs.com/nianheng/p/9895712.html