模板库
模板库
目录
图论
SPFA
#include<queue>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define X 2000007
using namespace std;
struct Edge {
int pre,to,w;
} edge[X];
queue<int>car;
int dis[X],num_edge,head[X];
bool if_q[X];
void add(int from,int to,int w) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
edge[num_edge].w=w;
head[from]=num_edge;
}
void spfa(int s) {
car.push(s);
int u,v;
if_q[s]=1,dis[s]=0;
while(!car.empty()) {
u=car.front(),if_q[u]=0;
for(int i=head[u]; i; i=edge[i].pre) {
v=edge[i].to;
if(edge[i].w+dis[u]<dis[v]) {
dis[v]=dis[u]+edge[i].w;
if(!if_q[v]) {
car.push(v);
if_q[v]=1;
}
}
}
car.pop();
}
}
int main() {
int n,m,u,v,w,S;
cin>>n>>m>>S;
for(int i=1; i<=n; ++i)
dis[i]=2147483647;
for(int i=1; i<=m; ++i) {
cin>>u>>v>>w;
add(u,v,w);
}
spfa(S);
for(int i=1; i<=n; ++i)
cout<<dis[i]<<" ";
return 0;
}
堆优化的Dijkstra
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
#define V 200007
#define ll long long
using namespace std;
int head[X],num_edge;
ll dis[X];
bool vis[X];
struct Edge {
int pre,to,w;
} edge[V];
struct Node {
int u;
ll diss;
bool operator<(const Node &B)const {
return diss>B.diss;
}
};
priority_queue<Node>car;
void add(int from,int to,int w) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
edge[num_edge].w=w;
head[from]=num_edge;
}
void dijkstra(int S) {
Node now,nex;
memset(dis,0x7f,sizeof(dis));
dis[S]=0;
now.diss=0,now.u=S;
car.push(now);
while(!car.empty()) {
now=car.top(),car.pop();
if(vis[now.u]) continue;
vis[now.u]=1;
for(int i=head[now.u]; i; i=edge[i].pre)
if(dis[edge[i].to]>dis[now.u]+edge[i].w) {
dis[edge[i].to]=dis[now.u]+edge[i].w;
if(!vis[edge[i].to]) {
nex.u=edge[i].to,nex.diss=dis[edge[i].to];
car.push(nex);
}
}
}
}
int main() {
int S,n,m,u,v,w;
scanf("%d%d%d",&n,&m,&S);
for(int i=1; i<=m; ++i) {
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dijkstra(S);
for(int i=1; i<=n; ++i)
printf("%lld ",dis[i]);
return 0;
}
Floyed
//... ...
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 107
using namespace std;
int dis[X][X];
int main() {
int n;
scanf("%d",&n);
memset(dis,0x3f,sizeof(dis));
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
scanf("%d",&dis[i][j]);
for(int k=1; k<=n; ++k)
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(dis[i][k]+dis[k][j]<dis[i][j])
dis[i][j]=dis[i][k]+dis[k][j];
return 0;
}
Kruskal
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,fa[100007],num_edge,ans;
struct Edge {
int from,to,w;
} edge[100007];
bool cmp(Edge x,Edge y) {
return x.w<y.w;
}
int find(int x) {
if(fa[x]!=x) return fa[x]=find(fa[x]);
return fa[x];
}
int uni(int x,int y) {
x=find(x),y=find(y);
if(x!=y) fa[y]=x;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i)
fa[i]=i;
for(int i=1; i<=m; ++i)
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].w);
sort(edge+1,edge+1+m,cmp);
int u,v,t=0;
for(int i=1; i<=m; ++i) {
u=edge[i].from,v=edge[i].to;
if(find(u)!=find(v)) {
uni(u,v);
ans=max(ans,edge[i].w);
++t;
if(t==n) break;
}
}
printf("%d %d",t,ans);
return 0;
}
最小费用最大流
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
#define V 1000007
using namespace std;
int head[V],car[X],dis[X],vio[X],reaflow[X];
int num_edge,n,m,Cost,Flow,h,t,S,T;
bool inq[X];
struct Edge {
int pre,from,to,c,w;
} edge[V];
void add(int from,int to,int c,int w) {
edge[++num_edge].pre=head[from];
edge[num_edge].from=from;
edge[num_edge].to=to;
edge[num_edge].c=c;
edge[num_edge].w=w;
head[from]=num_edge;
}
bool spfa() {
int now,tmp;
memset(dis,0x7f,sizeof(dis));
memset(reaflow,0x7f,sizeof(reaflow));
h=t=1,inq[S]=1,car[t++]=S,tmp=dis[0],dis[S]=0;
while(h<t) {
now=car[h++],inq[now]=0;
for(int i=head[now]; i; i=edge[i].pre) {
if(dis[now]+edge[i].w<dis[edge[i].to]&&edge[i].c>0) {
dis[edge[i].to]=edge[i].w+dis[now];
vio[edge[i].to]=i;
reaflow[edge[i].to]=min(reaflow[now],edge[i].c);
if(!inq[edge[i].to]) {
car[t++]=edge[i].to;
inq[edge[i].to]=1;
}
}
}
}
if(dis[T]==tmp) return 0;
return 1;
}
int main() {
int u,v,c,w;
scanf("%d%d%d%d",&n,&m,&S,&T);
for(int i=1; i<=m; ++i) {
scanf("%d%d%d%d",&u,&v,&c,&w);
add(u,v,c,w);
}
while(spfa()) {
Cost+=dis[T]*reaflow[T];
Flow+=reaflow[T];
for(int i=vio[T]; i; i=vio[edge[i].from]) {
edge[i].c-=reaflow[T];
add(edge[i].to,edge[i].from,reaflow[T],-edge[i].w);
}
}
printf("%d %d",Flow,Cost);
return 0;
}
求树的重心
//... ...
#include<cstdio>
#include<iostream>
#include<cstring>
#define INF 0x7fffffff
#define X 20007
using namespace std;
struct Edge {
int pre,to;
} edge[X<<1];
int head[X],siz[X],maxs[X],n,num_edge,num_node,ans;
//siz[i]为以i为根的子树大小,maxs[i]为删去i后最大子树大小
void add(int from,int to) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
void dfs(int now,int from) {
int v;
siz[now]++;
for(int i=head[now]; i; i=edge[i].pre) {
v=edge[i].to;
if(v==from)continue;
dfs(v,now);
siz[now]+=siz[v];
maxs[now]=max(maxs[now],siz[v]);
}
maxs[now]=max(maxs[now],n-siz[now]);
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
num_edge=0,num_node=INF;
memset(head,0,sizeof(head));
memset(siz,0,sizeof(siz));
memset(maxs,0,sizeof(maxs));
scanf("%d",&n);
int u,v;
for(int i=1; i<=n-1; i++) {
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs(1,0);
for(int i=1; i<=n; i++)
if(maxs[i]<num_node)
num_node=maxs[i],ans=i;
printf("%d %d\n",ans,num_node);
}
return 0;
}
LCA tarjian版
//... ...
#include<cstdio>
#include<iostream>
#define X 500007
using namespace std;
int head[X],fa[X],has[X],ans[X];
int num_edge,num_q;
bool vis[X];
struct Edge {
int pre,to;
} edge[X<<1];
struct Qs {
int pre,id,v;
} qs[X<<1];
void add(int from,int to) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
void add_Q(int u,int v,int tim) {
qs[++num_q].pre=has[u],qs[num_q].id=tim;
qs[num_q].v=v;
has[u]=num_q;
}
int find(int x) {
if(x!=fa[x]) return fa[x]=find(fa[x]);
return x;
}
void tar(int now) {
fa[now]=now,vis[now]=1;
for(int i=head[now]; i; i=edge[i].pre) {
if(!vis[edge[i].to]) {
tar(edge[i].to);
fa[edge[i].to]=now;
}
}
for(int i=has[now]; i; i=qs[i].pre)
if(vis[qs[i].v])
ans[qs[i].id]=find(qs[i].v);
}
int main() {
int n,m,s,u,v;
scanf("%d%d%d",&n,&m,&s);
for(int i=1; i<n; ++i) {
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
for(int i=1; i<=m; ++i) {
scanf("%d%d",&u,&v);
add_Q(u,v,i),add_Q(v,u,i);
}
tar(s);
for(int i=1; i<=m; ++i)
printf("%d\n",ans[i]);
return 0;
}
LCA 倍增版
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
const int MAX=500001;
int n,m,s,head[MAX],num_node,p,fa[MAX],f[MAX][20],id[MAX],S=1;
struct Node {
int pre,to;
} node[MAX*2];
void add(int from,int to) {
node[++num_node].pre=head[from];
node[num_node].to=to;
head[from]=num_node;
}
void dfs(int x) {
for(int i=head[x]; i; i=node[i].pre) {
if(!id[node[i].to]) {
id[node[i].to]=++S;
fa[node[i].to]=x;
dfs(node[i].to);
}
}
}
void pre() {
p=int(log(n)/log(2)+0.001);
for(int i=1; i<=n; ++i)
if(fa[i]) f[i][0]=fa[i];
for(int i=1; i<=p; ++i)
for(int j=1; j<=n; ++j)
f[j][i]=f[f[j][i-1]][i-1];
}
int ask(int x,int y) {
if(id[x]<id[y]) swap(x,y);
for(int i=p; i>=0; --i)
if(id[f[x][i]]>id[y])
x=f[x][i];
return f[x][0];
}
int main() {
scanf("%d%d%d",&n,&m,&s);
int from,to;
for(int i=1; i<=n-1; ++i) {
scanf("%d%d",&from,&to);
add(from,to);
add(to,from);
}
id[s]=1;
dfs(s);
pre();
int x,y;
for(int i=1; i<=m; ++i) {
scanf("%d%d",&x,&y);
printf("%d\n",ask(x,y));
}
return 0;
}
Tarjian 求割点
//... ...
#include<cstdio>
#include<iostream>
#define X 100007
#define V 200007
using namespace std;
int head[X],dfn[X],low[X];
int n,m,num_edge,tot,ans=0;
bool cutnode[X];
struct Edge {
int pre,to;
} edge[V];
void add(int from,int to) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
void tar(int now,int fa) {
int numson=0;
dfn[now]=low[now]=++tot;
for(int i=head[now]; i; i=edge[i].pre) {
if(edge[i].to==fa) continue;
if(!dfn[edge[i].to]) {
++numson;
tar(edge[i].to,now);
low[now]=min(low[now],low[edge[i].to]);
if(low[edge[i].to]>=dfn[now])
cutnode[now]=1;
} else low[now]=min(low[now],dfn[edge[i].to]);
}
if(!fa&&numson<2) cutnode[now]=0;
if(cutnode[now]) ++ans;
}
int main() {
int u,v;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; ++i) {
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
for(int i=1; i<=n; ++i)
if(!dfn[i]) tar(i,0);
printf("%d\n",ans);
for(int i=1; i<=n; ++i)
if(cutnode[i]) printf("%d ",i);
return 0;
}
Tarjian 缩点
//... ...
#include<cstdio>
#include<iostream>
#define X 10007
#define V 50007
using namespace std;
int dfn[X],low[X],siz[X],bel[X],stack[X],outdu[X],lik[X];
int tot,cnt;
struct Graph {
int num_edge,head[X];
struct Edge {
int pre,to;
} edge[V];
void add(int from,int to) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
} G1;
void tar(int now) {
dfn[now]=low[now]=++cnt,stack[++stack[0]]=now;
for(int i=G1.head[now]; i; i=G1.edge[i].pre) {
if(!dfn[G1.edge[i].to]) {
tar(G1.edge[i].to);
low[now]=min(low[now],low[G1.edge[i].to]);
} else low[now]=min(low[now],dfn[G1.edge[i].to]);
}
if(dfn[now]==low[now]) {
int num=0;
++tot;
while(stack[0]) {
bel[stack[stack[0]--]]=tot,++num;
if(stack[stack[0]+1]==now) break;
}
lik[tot]=siz[tot]=num;
}
}
int main() {
int n,m,u,v,now,ans=0,wtc;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; ++i) {
scanf("%d%d",&u,&v);
G1.add(u,v);
}
for(int i=1; i<=n; ++i)
if(!dfn[i]) tar(i);
for(int i=1; i<=n; ++i)
for(int j=G1.head[i]; j; j=G1.edge[j].pre)
if(bel[i]!=bel[G1.edge[j].to])
++outdu[bel[i]];
for(int i=1; i<=tot; ++i)
if(!outdu[i]) ++ans,wtc=i;
if(ans==1)
printf("%d",siz[wtc]);
else printf("0");
return 0;
}
差分约束
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
#define V 10000007
#define ll long long
using namespace std;
int head[X],num_edge;
queue<int>car;
int tim[X],N,K;
ll dis[X];
bool inq[X];
struct Edge {
int pre,to,w;
} edge[V];
void add(int from,int to,int w) {
edge[++num_edge].pre=head[from];
edge[num_edge].to=to;
edge[num_edge].w=w;
head[from]=num_edge;
}
ll SPFA() {
for(int i=1; i<=N; ++i)
car.push(i),dis[i]=1,inq[i]=1,tim[i]=1;
int now;
while(!car.empty()) {
now=car.front(),car.pop(),inq[now]=0;
for(int i=head[now]; i; i=edge[i].pre)
if(dis[now]+edge[i].w>dis[edge[i].to]) {
dis[edge[i].to]=dis[now]+edge[i].w;
if(!inq[edge[i].to]) {
car.push(edge[i].to),inq[edge[i].to]=1;
if(++tim[edge[i].to]>=N) return -1;
}
}
}
ll sum=0;
for(int i=1; i<=N; ++i)
sum+=dis[i];
return sum;
}
int main() {
int x,u,v;
ll ans;
scanf("%d%d",&N,&K);
for(int i=1; i<=K; ++i) {
scanf("%d%d%d",&x,&u,&v);
if(x==1)
add(v,u,0),add(u,v,0);
else if(x==2) {
if(u==v) {
printf("-1");
return 0;
}
add(u,v,1);
} else if(x==3) add(v,u,0);
else if(x==4) {
if(u==v) {
printf("-1");
return 0;
}
add(v,u,1);
} else add(u,v,0);
}
ans=SPFA();
cout<<ans;
return 0;
}
二分图带权匹配
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 305;
const int INF = 0x3f3f3f3f;
int love[MAXN][MAXN];
int ex_girl[MAXN],ex_boy[MAXN];
bool vis_girl[MAXN],vis_boy[MAXN];
int match[MAXN],slack[MAXN];
int N;
bool dfs(int girl) {
vis_girl[girl] = true;
for (int boy = 0; boy < N; ++boy) {
if (vis_boy[boy]) continue;
int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
if (gap == 0) {
vis_boy[boy] = true;
if (match[boy] == -1 || dfs( match[boy] )) {
match[boy] = girl;
return true;
}
} else {
slack[boy] = min(slack[boy], gap);
}
}
return false;
}
int KM() {
memset(match, -1, sizeof match);
memset(ex_boy, 0, sizeof ex_boy);
for (int i = 0; i < N; ++i) {
ex_girl[i] = love[i][0];
for (int j = 1; j < N; ++j) {
ex_girl[i] = max(ex_girl[i], love[i][j]);
}
}
for (int i = 0; i < N; ++i) {
fill(slack, slack + N, INF);
while (1) {
memset(vis_girl, false, sizeof vis_girl);
memset(vis_boy, false, sizeof vis_boy);
if (dfs(i)) break;
int d = INF;
for (int j = 0; j < N; ++j)
if (!vis_boy[j]) d = min(d, slack[j]);
for (int j = 0; j < N; ++j) {
if (vis_girl[j]) ex_girl[j] -= d;
if (vis_boy[j]) ex_boy[j] += d;
else slack[j] -= d;
}
}
}
int res = 0;
for (int i = 0; i < N; ++i)
res += love[ match[i] ][i];
return res;
}
int main() {
while (~scanf("%d", &N)) {
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
scanf("%d", &love[i][j]);
printf("%d\n", KM());
}
return 0;
}
数学
GCD
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
同余方程 (含扩欧)
#include<iostream>
using namespace std;
int extend_gcd(int a,int b,int &x,int &y){
if(b==0){
x=1;y=0;
return a;
}
else {
int r=extend_gcd(b,a%b,x,y);
int t=x-a/b*y;
x=y;y=t;
return r;
}
}
int main(){
int a,b,x,y;
cin>>a>>b;
extend_gcd(a,b,x,y);
while(x<0)
x=x+b;
cout<<x;
return 0;
}
最小公倍数
\(LCM(a,b)=\frac{a*b}{gcd(a,b)}\) .
设\(a_i=\prod_{j=1} prime_j^{xi}\) .
则\(LCM(a_i)=\prod_{j=1}prime_j^{max(xi)},i\in[1,n]\) .
线性筛素数
void sieve(int x) {
memset(isPrime,1,sizeof(isPrime));
isPrime[0]=isPrime[1]=0;
for(int i=2; i<=x; ++i) {
if(isPrime[i]) prime[++tot]=i;
for(int j=1; j<=tot&&i*prime[j]<=x; ++j) {
isPrime[i*prime[j]]=0;
if(i%prime[j]==0) break;
}
}
}
筛欧拉函数\(\phi(x)\)
phi[1]=1;
for(int i=2; i<=N; i++) {
if(!mark[i]) prime[++tot]=i,phi[i]=i-1;
for(int j=1; j<=tot&&i*prime[j]<=N; j++) {
mark[i*prime[j]]=1;
if(i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1);
//欧拉函数是积性函数,phi[i*prime[j]]=phi[i]*phi[prime[j]].
//而由于prime[j]是素数,所以phi[prime[j]]=prime[j]-1;
else {
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
线性求逆元
\(A_i=(p-p/i)*A_{p\%i}\%p\)
费马小定理求逆元
\(a^{-1}=a^{p-2}(\mod p),p\)为质数.
欧拉定理
若\(n,a\)为正整数,且\(n,a\)互质,则
\(a^{-1}=a^{\phi(p)-1}(mod\ p)\).
组合数递推式
\(C[i][0]=1\)
\(C(n,m)=C(n-1,m-1)+C(n,m-1)\)
高斯消元
//... ...
#include<cmath>
#include<cstdio>
#include<iostream>
#define X 107
using namespace std;
double a[X][X],x[X];
int n;
double del;
bool guass() {
for(int i=1; i<=n; ++i) {
int p=i;
for(int j=i+1; j<=n; ++j)
if(fabs(a[j][i])>fabs(a[p][i]))
p=j;
if(fabs(a[p][i])<1e-8) return 0;
if(p!=i)
for(int j=i; j<=n+1; ++j)
swap(a[i][j],a[p][j]);
for(int j=i+1; j<=n; ++j) {
del=a[i][i]/a[j][i];
for(int k=i; k<=n+1; ++k)
a[j][k]=a[i][k]-del*a[j][k];
}
}
for(int i=n; i; --i) {
for(int j=n; j>i; --j)
a[i][n+1]-=a[i][j]*x[j];
x[i]=a[i][n+1]/a[i][i];
}
return 1;
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; ++i)
for(int j=1; j<=n+1; ++j)
scanf("%lf",&a[i][j]);
if(guass())
for(int i=1; i<=n; ++i)
printf("%.2lf\n",x[i]);
else printf("No Solution");
return 0;
}
错位排列
如果一个\(n\)的全排列满足\(\forall a_i\neq i\),
则称它是一个错位排列.方案数\(D(n)=(n-1)(D(n-1)+D(n-2)))\) .
中国剩余定理 CRT
#include<cstdio>
#include<iostream>
#define X 17
#define ll long long
using namespace std;
ll a[X],m[X],SM,d;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1,y=0;
return a;
}
ll ret=exgcd(b,a%b,x,y);
ll tmp=x;
x=y,y=tmp-a/b*y;
return ret;
}
ll CRT(){
ll x,y,ans=0,Mi;
for(ll i=1;i<=3;++i){
Mi=SM/m[i];
exgcd(Mi,m[i],x,y);
ans+=Mi*x*a[i];
}
while(ans>d) ans-=SM;
while(ans<=d) ans+=SM;
return ans-d;
}
int main(){
int tot=0;
m[1]=23,m[2]=28,m[3]=33,SM=21252;
while(scanf("%lld%lld%lld%lld",&a[1],&a[2],&a[3],&d)){
++tot;
if(a[1]==-1) break;
printf("Case %d: the next triple peak occurs in %lld days.\n",tot,CRT());
}
return 0;
}
Lucas 定理
//... ...
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
ll p;
ll ksm(ll n,ll m) {
ll ans=1,now=n;
while(m) {
if(m&1) ans=(ans*now)%p;
now=(now*now)%p,m>>=1;
}
return ans%p;
}
ll cm(ll n,ll m) {
if(n<m) return 0;
if(m>n-m) m=n-m;
long long s1=1,s2=1;
for(ll i=0; i<m; ++i)
s1=s1*(n-i)%p,s2=s2*(i+1)%p;
return s1*ksm(s2,p-2)%p;
}
ll Lucas(ll n,ll m) {
if(!m) return 1;
return cm(n%p,m%p)*Lucas(n/p,m/p)%p;
}
int main() {
ll n,m,T;
scanf("%lld",&T);
while(T--) {
scanf("%lld%lld%lld",&n,&m,&p);
printf("%lld\n",Lucas(n+m,m));
}
return 0;
}
Miller-Rabin 素性测试
#include<cstdio>
#include<iostream>
using namespace std;
int prime[]={0,2,3,5,7,11};
long long ksm(int n,int m,int mod){
int ans=1,now=n;
while(m){
if(m&1) ans*=now,ans%=mod;
now*=now,now%=mod,m>>=1;
}
return ans;
}
bool Miller_Rabin(int a,int x){
int s=0,d=x-1;
while(d&&(!(d&1))) ++s,d>>=1;
long long k=ksm(a,d,x);
if(k==1||k==x-1) return 1;
for(int i=1;i<=s;++i){
k=k*k%x;
if(k==x-1) return 1;
}
return 0;
}
bool Judge(int x){
if(x==1) return 0;
for(int i=1;i<=5;++i){
if(x==prime[i]) return 1;
if(!(x%prime[i])) return 0;
if(!Miller_Rabin(prime[i],x)) return 0;
}
return 1;
}
int main(){
int T,l,r;
cin>>T;
while(T--){
cin>>l>>r;
for(int i=l;i<=r;++i)
if(Judge(i)) printf("%d\n",i);
printf("\n");
}
return 0;
}
快速乘与快速幂
//... ...快速乘与快速幂(可带%)
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
ll ksc(ll n,ll m) {
ll ans=0,now=n,f=1; //f是用来存负号的
if(now<0) f=-1,now=-now;
if(m<0) f=-f,m=-m;
while(m) {
if(m&1) ans+=now;
now+=now,m>>=1;
}
return ans*f;
}
ll ksm(ll n,ll m) {
int ans=1,now=n;
while(m) {
if(m&1) ans*=now;
now*=now,m>>=1;
}
return ans;
}
int main() {
return 0;
}
筛莫比乌斯函数
//... ...
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
using namespace std;
int mu[X],prime[X],tot;
bool is_Prime[X];
void sieve(int x) {
mu[1]=1;
memset(is_Prime,1,sizeof(is_Prime));
is_Prime[0]=is_Prime[1]=0;
for(int i=2; i<=x; i++) {
if(is_Prime[i]) {
prime[++tot]=i;
mu[i]=-1;
}
for(int j=1; prime[j]*i<=x; j++) {
is_Prime[prime[j]*i]=0;
if(i%prime[j]==0) {
mu[prime[j]*i]=0;
break;
}
mu[prime[j]*i]=-mu[i];
}
}
}
int main() {
int n;
scanf("%d",&n);
sieve(n);
return 0;
}
数据结构
Splay
//... ...
#include<cstdio>
#include<iostream>
#define X 100007
using namespace std;
int root,kep,n,tot;
int fa[X],data[X],ch[X][2],siz[X],cnt[X];
void pushup(int rt) {
int l=ch[rt][0],r=ch[rt][1];
siz[rt]=siz[l]+siz[r]+cnt[rt];
}
void rotate(int x,int &k) {
int a=fa[x],b=fa[a],l,r;
l= (ch[a][0]!=x);
r= l^1;
if(a==k) k=x;
else
ch[b][ch[b][1]==a]=x;
fa[x]=b,fa[a]=x,fa[ch[x][r]]=a;
ch[a][l]=ch[x][r],ch[x][r]=a;
pushup(a);
}
void splay(int x,int &k) {
int a,b;
while(x!=k) {
a=fa[x],b=fa[a];
if(a!=k) {
if((ch[a][0]==x)^(ch[b][0]==a))
rotate(x,k);
else
rotate(a,k);
}
rotate(x,k);
pushup(x);
}
}
void ins(int &rt,int x) {
if(rt==0) {
rt=++kep;
data[kep]=x;
siz[kep]=cnt[kep]=1;
return;
}
if(x==data[rt]) {
cnt[rt]++;
siz[rt]++;
return;
}
if(x<data[rt]) {
ins(ch[rt][0],x);
fa[ch[rt][0]]=rt;
pushup(rt);
} else {
ins(ch[rt][1],x);
fa[ch[rt][1]]=rt;
pushup(rt);
}
}
int getmn(int rt) {
while(ch[rt][0]) {
rt=ch[rt][0];
}
if(!rt) return -1;
return rt;
}
void del(int rt,int x) {
if(data[rt]==x) {
if(cnt[rt]>1) {
cnt[rt]--;
siz[rt]--;
} else {
splay(rt,root);
int p=getmn(ch[rt][1]);
if(p!=-1) {
splay(p,root);
fa[p]=0;
ch[p][0]=ch[rt][0];
fa[ch[rt][0]]=p;
pushup(p);
} else {
root=ch[rt][0];
fa[ch[rt][0]]=0;
}
}
return;
}
if(x<data[rt]) {
del(ch[rt][0],x);
pushup(rt);
} else {
del(ch[rt][1],x);
pushup(rt);
}
}
int getpre(int rt,int x) {
int p=rt,ans;
while(p) {
if(x<=data[p]) {
p=ch[p][0];
} else {
ans=p;
p=ch[p][1];
}
}
return ans;
}
int getsuc(int rt,int x) {
int p=rt,ans;
while(p) {
if(x>=data[p]) {
p=ch[p][1];
} else {
ans=p;
p=ch[p][0];
}
}
return ans;
}
int geth(int rt,int k) {
if(data[rt]==k) {
splay(rt,root);
if(ch[rt][0]==0) {
return 1;
} else {
return siz[ch[rt][0]]+1;
}
}
if(k<data[rt]) return geth(ch[rt][0],k);
else return geth(ch[rt][1],k);
}
int getkth(int rt,int k) {
int l=ch[rt][0];
if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return data[rt];
if(k<siz[l]+1) return getkth(ch[rt][0],k);
if(siz[l]+cnt[rt]<k) return getkth(ch[rt][1],k-(siz[l]+cnt[rt]));
}
int main() {
int opt,x;
scanf("%d",&n);
while(n--) {
scanf("%d%d",&opt,&x);
if(opt==1) {
tot++;
ins(root,x);
}
if(opt==2) {
tot--;
del(root,x);
}
if(opt==3) {
printf("%d\n",geth(root,x));
}
if(opt==4) {
printf("%d\n",getkth(root,x));
}
if(opt==5) {
printf("%d\n",data[getpre(root,x)]);
}
if(opt==6) {
printf("%d\n",data[getsuc(root,x)]);
}
}
return 0;
}
线段树
#include<cstdio>
#include<iostream>
#define X 100005
using namespace std;
long long askl,askr,ans,add;
struct Tree {
long long l,r,w,f;
} tree[X<<2];
void pushdown(long long k) {
tree[k<<1].f+=tree[k].f;
tree[k<<1|1].f+=tree[k].f;
tree[k<<1].w+=tree[k].f*(tree[k<<1].r-tree[k<<1].l+1);
tree[k<<1|1].w+=tree[k].f*(tree[k<<1|1].r-tree[k<<1|1].l+1);
tree[k].f=0;
}
void build(long long k,long long l,long long r) {
tree[k].l=l,tree[k].r=r;
if(tree[k].l==tree[k].r) {
scanf("%lld",&tree[k].w);
return ;
}
long long mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
}
void change_nevl(long long k) {
if(askl<=tree[k].l&&tree[k].r<=askr) {
tree[k].f+=add;
tree[k].w+=add*(tree[k].r-tree[k].l+1);
return ;
}
if(tree[k].f) pushdown(k);
long long mid=(tree[k].l+tree[k].r)>>1;
if(askl<=mid) change_nevl(k<<1);
if(askr>mid) change_nevl(k<<1|1);
tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
}
void ask_nevl(long long k) {
if(askl<=tree[k].l&&tree[k].r<=askr) {
ans+=tree[k].w;
return;
}
if(tree[k].f) pushdown(k);
long long mid=(tree[k].l+tree[k].r)>>1;
if(askl<=mid) ask_nevl(k<<1);
if(askr>mid) ask_nevl(k<<1|1);
}
int main() {
long long n,m,t;
cin>>n>>m;
build(1,1,n);
while(m--) {
cin>>t;
if(t==1) {
cin>>askl>>askr>>add;
change_nevl(1);
} else {
cin>>askl>>askr;
ans=0;
ask_nevl(1);
cout<<ans<<endl;
}
}
return 0;
}
树状数组
#include<cstdio>
#include<iostream>
#define X 500007
using namespace std;
int n,m,c[X];
inline int lowbit(int x) {
return x&(-x);
}
void add(int p,int x) {
while(p<=n)
c[p]+=x,p+=lowbit(p);
}
int getnevl(int r) {
int ans=0;
while(r)
ans+=c[r],r-=lowbit(r);
return ans;
}
int main() {
int x,a,c;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) {
scanf("%d",&x);
add(i,x);
}
while(m--) {
scanf("%d%d%d",&a,&x,&c);
if(a==1)
add(x,c);
else printf("%d\n",getnevl(c)-getnevl(x-1));
}
return 0;
}
替罪羊树
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define INF (1<<30)
#define X (2100000)
#define al (0.75)
using namespace std;
struct node {
int son[2],fa,size,num;
} t[X];
int n,cnt,root,cur[X],sum;
bool balance(int x) { //平衡限制,这里的 alpha 取0.75
return (double)t[x].size*al>=(double)t[t[x].son[0]].size
&& (double) t[x].size*al>=(double)t[t[x].son[1]].size;
}
void recycle(int id) { //压扁成一个序列,按大小顺序回收节点
if(t[id].son[0]) recycle(t[id].son[0]);
cur[++sum]=id;
if(t[id].son[1]) recycle(t[id].son[1]);
}
int build(int l,int r) { //递归建树
if(l>r) return 0;
int mid=(l+r)>>1,id=cur[mid];
t[id].son[0]=build(l,mid-1),t[t[id].son[0]].fa=id;
t[id].son[1]=build(mid+1,r),t[t[id].son[1]].fa=id;
t[id].size=t[t[id].son[0]].size+t[t[id].son[1]].size+1;
return id;
}
void rebuild(int id) { //重构
sum=0;
recycle(id);
int fa=t[id].fa,Son=(t[t[id].fa].son[1]==id);
int cur=build(1,sum);
t[fa].son[Son]=cur,t[cur].fa=fa;
if(id==root) root=cur;
}
void ins(int x) {
int now=root,cur=++cnt;
t[cur].size=1,t[cur].num=x;
while(1) { //插入维护序列,左小右大
t[now].size++;
bool Son=(x>=t[now].num);
if( t[now].son[Son] ) now=t[now].son[Son];
else {
t[now].son[Son]=cur,t[cur].fa=now;
break;
}
}
int flag=0;
for(int i=cur; i; i=t[i].fa) if(!balance(i)) flag=i;
if(flag) rebuild(flag); //插入往往会导致不平衡,这时只需要重建不平衡的子树即可
}
int get_num(int x) { //查询 x 在树中的节点编号
int now=root;
while(1) {
if(t[now].num==x) return now;
else now=t[now].son[x>t[now].num];
}
}
void del(int id) { //删除
if(t[id].son[0] && t[id].son[1]) {
int cur=t[id].son[0];
while(t[cur].son[1]) cur=t[cur].son[1];
t[id].num=t[cur].num;
id=cur;
} //删除操作需要找到左子树的最后一个节点或右子树的第一个节点来顶替,优先找左子树
int Son=(t[id].son[0]) ? t[id].son[0]:t[id].son[1];
int k=(t[t[id].fa].son[1]==id );
t[t[id].fa].son[k]=Son,t[Son].fa=t[id].fa;
for(int i=t[id].fa; i; i=t[i].fa) t[i].size--;
if(id==root) root=Son;
}
int getk(int x) { //查 x 的排名
int now=root,ans=0;
while(now) {
if(t[now].num<x) ans+=t[t[now].son[0]].size+1,now=t[now].son[1];
else now=t[now].son[0];
}
return ans;
}
int getkth(int x) { //查树中的第 k 个数
int now=root;
while(1) {
if(t[t[now].son[0]].size==x-1) return now;
else if(t[t[now].son[0]].size>=x) now=t[now].son[0];
else x-=t[t[now].son[0]].size+1,now=t[now].son[1];
}
return now;
}
int getpre(int x) { //找前驱,即左子树最后一个点
int now=root,ans=-INF;
while(now) {
if(t[now].num<x) ans=max(ans,t[now].num),now=t[now].son[1];
else now=t[now].son[0];
}
return ans;
}
int getsuc(int x) { //找后继,即右子树第一个点
int now=root,ans=INF;
while(now) {
if(t[now].num>x) ans=min(ans,t[now].num),now=t[now].son[0];
else now=t[now].son[1];
}
return ans;
}
int main() {
cnt=2,root=1;
t[1].num=-INF,t[1].size=2,t[1].son[1]=2;
t[2].num=INF,t[2].size=1,t[2].fa=1;
scanf("%d",&n);
int opt,x;
for(int i=1; i<=n; i++) {
scanf("%d%d",&opt,&x);
if(opt==1) ins(x);
if(opt==2) del( get_num(x) );
if(opt==3) printf("%d\n",getk(x));
if(opt==4) printf("%d\n",t[ getkth(x+1) ].num);
if(opt==5) printf("%d\n",getpre(x));
if(opt==6) printf("%d\n",getsuc(x));
}
return 0;
}
笛卡尔树
//... ...cogs2421
#include<cstdio>
#include<algorithm>
#define MAXN 500010
using namespace std;
struct Tree {
int key,th;
Tree *ch[2];
}*car[MAXN],node[MAXN],*root;
int top,n;
int cmp(const Tree a,const Tree b) {
return a.key<b.key;
}
inline void built() {
car[++top]=node+1;
for(int i=2; i<=n; i++) {
Tree *last=NULL;
while(top&&car[top]->th>node[i].th)
last=car[top--];
if(top) car[top]->ch[1]=node+i;
node[i].ch[0]=last;
car[++top]=node+i;
}
root=car[1];
}
void dfs(Tree *rt) {
if(!rt)return;
printf("%d ",rt->key);
dfs(rt->ch[0]);
dfs(rt->ch[1]);
}
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&node[i].key);
for(int i=1; i<=n; i++) scanf("%d",&node[i].th);
sort(node+1,node+n+1,cmp);
built();
dfs(root);
return 0;
}
主席树
//... ...
#include<cstdio>
#include<iostream>
#include<algorithm>
#define X 200007
using namespace std;
int cnt,n,ref[X],a[X],son[X*18][2],sum[X*18],root[X],tot;
void discrete() {
sort(ref+1,ref+1+n);
cnt=1;
for(int i=2; i<=n; ++i)
if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int i=1; i<=n; ++i) a[i]=lower_bound(ref+1,ref+1+cnt,a[i])-ref;
}
void built(int x,int &y,int l,int r,int pos) {
sum[y=++tot]=sum[x]+1;
if(l==r) return;
int mid=l+r>>1;
if(pos<=mid) son[y][1]=son[x][1],built(son[x][0],son[y][0],l,mid,pos);
else son[y][0]=son[x][0],built(son[x][1],son[y][1],mid+1,r,pos);
}
int find_pos(int x,int y,int l,int r,int k) {
if(l==r) return l;
int mid=l+r>>1,tmp=sum[son[y][0]]-sum[son[x][0]];
if(k<=tmp) return find_pos(son[x][0],son[y][0],l,mid,k);
else return find_pos(son[x][1],son[y][1],mid+1,r,k-tmp);
}
int main() {
int m,l,r,k;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) {
scanf("%d",&a[i]);
ref[i]=a[i];
}
discrete();
for(int i=1; i<=n; ++i)
built(root[i-1],root[i],1,cnt,a[i]);
while(m--) {
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",ref[find_pos(root[l-1],root[r],1,cnt,k)]);
}
return 0;
}
ST表
//... ...
#include<cstdio>
#include<iostream>
#define X 100007
using namespace std;
int n,f_max[X][27],a[X],lg2[X];
void pre() {
lg2[0]=-1;
for(int i=1; i<=n; ++i) {
lg2[i]=((i&(i-1))==0)? lg2[i-1]+1:lg2[i-1];
f_max[i][0]=a[i];
}
for(int i=1; i<=lg2[n]; ++i)
for(int j=1; j+(1<<i)-1<=n; ++j)
f_max[j][i]=max(f_max[j][i-1],f_max[j+(1<<(i-1))][i-1]);
}
inline int getmax(int l,int r) {
int k=lg2[r-l+1];
return max(f_max[l][k],f_max[r-(1<<k)+1][k]);
}
int main() {
int m,l,r,ans;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
pre();
while(m--) {
scanf("%d%d",&l,&r);
ans=getmax(l,r);
printf("%d\n",ans);
}
return 0;
}
高精度
//Author : ZlycerQan
#include <cstdio>
#include <iostream>
#include <vector>
#include <iomanip>
#include <cassert>
#include <algorithm>
#include <cstring>
const int Big_B = 1000000000;
const int Big_L = 9;
inline int intcmp_ (int a, int b) {
if (a > b) return 1;
return a < b ? -1 : 0;
}
struct Int {
#define rg register
inline int max (int a, int b) {
return a > b ? a : b;
}
inline int min (int a, int b) {
return a < b ? a : b;
}
std :: vector <int> c;
Int () {} typedef long long LL;
Int (int x) {
for (; x > 0; c.push_back (x % Big_B), x /= Big_B);
}
Int (LL x) {
for (; x > 0; c.push_back (x % Big_B), x /= Big_B);
}
inline void CrZ () {
for (; !c.empty () && c.back () == 0; c.pop_back ());
}
inline Int &operator += (const Int &rhs) {
c.resize (max (c.size (), rhs.c.size ()));
rg int i, t = 0, S;
for (i = 0, S = rhs.c.size (); i < S; ++ i)
c[i] += rhs.c[i] + t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
c[i] += t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
if (t) c.push_back (t);
return *this;
}
inline Int &operator -= (const Int &rhs) {
c.resize (max (c.size (), rhs.c.size ()));
rg int i, t = 0, S;
for (i = 0, S = rhs.c.size (); i < S; ++ i)
c[i] -= rhs.c[i] + t, t = c[i] < 0, c[i] += Big_B & (-t);
for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
c[i] -= t, t = c[i] < 0, c[i] += Big_B & (-t);
CrZ ();
return *this;
}
inline Int &operator *= (const Int &rhs) {
rg int na = c.size (), i, j, S, ai;
c.resize (na + rhs.c.size ());
LL t;
for (i = na - 1; i >= 0; -- i) {
ai = c[i], t = 0, c[i] = 0;
for (j = 0, S = rhs.c.size (); j < S; ++ j) {
t += c[i + j] + (LL) ai * rhs.c[j];
c[i + j] = t % Big_B, t /= Big_B;
}
for (j = rhs.c.size (), S = c.size (); t != 0 && i + j < S; ++ j)
t += c[i + j], c[i + j] = t % Big_B, t /= Big_B;
assert (t == 0);
}
CrZ ();
return *this;
}
inline Int &operator /= (const Int &rhs) {
return *this = div (rhs);
}
inline Int &operator %= (const Int &rhs) {
return div (rhs), *this;
}
inline Int &shlb (int l = 1) {
if (c.empty ()) return *this;
c.resize (c.size () + l);
rg int i;
for (i = c.size () - 1; i >= l; -- i) c[i] = c[i - l];
for (i = 0; i < l; ++ i) c[i] = 0;
return *this;
}
inline Int &shrb (int l = 1) {
for (rg int i = 0; i < c.size () - l; ++ i) c[i] = c[i + l];
c.resize (max (c.size () - l, 0));
return *this;
}
inline int Comp (const Int &rhs) const {
if (c.size () != rhs.c.size ()) return intcmp_ (c.size (), rhs.c.size ());
for (rg int i = c.size () - 1; i >= 0; -- i)
if (c[i] != rhs.c[i]) return intcmp_ (c[i], rhs.c[i]);
return 0;
}
inline Int div (const Int &rhs) {
assert (!rhs.c.empty ());
Int q, r;
rg int i;
if (rhs > *this) return 0;
q.c.resize (c.size () - rhs.c.size () + 1);
rg int _l, _r, mid;
for (i = c.size () - 1; i > c.size () - rhs.c.size (); -- i) r.shlb (), r += c[i];
for (i = c.size () - rhs.c.size (); i >= 0; -- i) {
r.shlb ();
r += c[i];
if (r.Comp (rhs) < 0) q.c[i] = 0;
else {
_l = 0, _r = Big_B;
for (; _l != _r; ) {
mid = _l + _r >> 1;
if ((rhs * mid).Comp (r) <= 0) _l = mid + 1;
else _r = mid;
}
q.c[i] = _l - 1, r -= rhs * q.c[i];
}
}
q.CrZ (), *this = r;
return q;
}
friend inline Int operator + (const Int &lhs, const Int &rhs) {
Int res = lhs;
return res += rhs;
}
friend inline Int operator - (const Int &lhs, const Int &rhs) {
Int res = lhs;
return res -= rhs;
}
friend inline Int operator * (const Int &lhs, const Int &rhs) {
Int res = lhs;
return res *= rhs;
}
friend inline Int operator / (const Int &lhs, const Int &rhs) {
Int res = lhs;
return res.div (rhs);
}
friend inline Int operator % (const Int &lhs, const Int &rhs) {
Int res = lhs;
return res.div (rhs), res;
}
friend inline std :: ostream &operator << (std :: ostream &out, const Int &rhs) {
if (rhs.c.size () == 0) out << "0";
else {
out << rhs.c.back ();
for (rg int i = rhs.c.size () - 2; i >= 0; -- i)
out << std :: setfill ('0') << std :: setw (Big_L) << rhs.c[i];
}
return out;
}
friend inline std :: istream &operator >> (std :: istream &in, Int &rhs) {
static char s[10000];
in >> s + 1;
int Len = strlen (s + 1);
int v = 0;
LL r = 0, p = 1;
for (rg int i = Len; i >= 1; -- i) {
++ v;
r = r + (s[i] - '0') * p, p *= 10;
if (v == Big_L) rhs.c.push_back (r), r = 0, v = 0, p = 1;
}
if (v != 0) rhs.c.push_back (r);
return in;
}
friend inline bool operator < (const Int &lhs, const Int &rhs) {
return lhs.Comp (rhs) < 0;
}
friend inline bool operator <= (const Int &lhs, const Int &rhs) {
return lhs.Comp (rhs) <= 0;
}
friend inline bool operator > (const Int &lhs, const Int &rhs) {
return lhs.Comp (rhs) > 0;
}
friend inline bool operator >= (const Int &lhs, const Int &rhs) {
return lhs.Comp (rhs) >= 0;
}
friend inline bool operator == (const Int &lhs, const Int &rhs) {
return lhs.Comp (rhs) == 0;
}
friend inline bool operator != (const Int &lhs, const Int &rhs) {
return lhs.Comp (rhs) != 0;
}
#undef rg
};
Int a;
int main () {
return 0;
}
字符串
KMP
//... ...
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 1000007
using namespace std;
char s[X],p[X];
int nex[X];
int main() {
int lens,lenp,j;
cin>>s+1>>p+1;
lens=strlen(s+1),lenp=strlen(p+1);
j=0;
for(int i=2; i<=lenp; ++i) {
while(j&&p[i]!=p[j+1]) j=nex[j];
if(p[i]==p[j+1]) ++j;
nex[i]=j;
}
j=0;
for(int i=1; i<=lens; ++i) {
while(j&&s[i]!=p[j+1]) j=nex[j];
if(s[i]==p[j+1]) ++j;
if(j==lenp){
printf("%d\n",i-lenp+1);
j=nex[j];
}
}
for(int i=1; i<=lenp; ++i)
printf("%d ",nex[i]);
return 0;
}
AC自动机
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char ss[161][81],s[1001001];
int tot,bl[151*81],mp[151],trie[151*81][27],f[151*81],sum[151];
queue<int>car;
struct AhoCorasickAutomata {
void insert(int j) {
int rt=1,len=strlen(ss[j]),id;
for(int i=0; i<len; ++i) {
id=ss[j][i]-'a';
if(!trie[rt][id]) {
trie[rt][id]=++tot;
bl[tot]=0;
memset(trie[tot],0,sizeof(trie[tot]));
}
rt=trie[rt][id];
}
if(!bl[rt]) bl[rt]=j;
mp[j]=bl[rt];
}
void getfail() {
memset(f,0,sizeof(f));
for(int i=0; i<26; ++i) trie[0][i]=1;
int rt=1,j,now;
car.push(1);
while(!car.empty()) {
now=car.front();
car.pop();
for(int i=0; i<26; ++i) {
if(!trie[now][i]) continue;
car.push(trie[now][i]);
j=f[now];
while(!trie[j][i]) j=f[j];
f[trie[now][i]]=trie[j][i];
}
}
}
void find() {
memset(sum,0,sizeof(sum));
int rt=1,len=strlen(s),id,j;
for(int i=0; i<len; ++i) {
id=s[i]-'a';
while(!trie[rt][id]) rt=f[rt];
j=rt=trie[rt][id];
while(j)
++sum[bl[j]],j=f[j];
}
}
} AC;
int main() {
int n,ans;
while(scanf("%d",&n)) {
if(!n) return 0;
ans=0;
tot=1;
memset(trie[1],0,sizeof(trie[1]));
memset(mp,0,sizeof(mp));
for(int i=1; i<=n; ++i) {
scanf("%s",ss[i]);
AC.insert(i);
}
AC.getfail();
scanf("%s",s);
AC.find();
for(int i=1; i<=n; ++i)
ans=max(ans,sum[i]);
printf("%d\n",ans);
for(int i=1; i<=n; ++i)
if(sum[mp[i]]==ans) puts(ss[i]);
}
}