模板
1.读入优化
inline int read() { int ans=0,f=1;char t=getchar(); while(t<'0'||t>'9') f=(t=='-'?-1:1),t=getchar(); while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar(); return ans*f; }
2.并查集
#include<cstdio> #include<cstring> const int N=10010; int fa[N]; inline int get(int x){if(fa[x]==x) return x;return fa[x]=get(fa[x]);} int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; int flag,x,y; for(int i=1;i<=m;i++) { scanf("%d %d %d",&flag,&x,&y); if(flag==1) fa[get(x)]=get(y); else{if(get(x)==get(y)) printf("Y\n");else printf("N\n");} } return 0; }
3.最小生成树
#include<cstdio> #include<cstring> #include<algorithm> using std::sort; using std::max; const int N=200010; struct node { int v,u,p; }e[N]; int fa[5050]; bool cmp(node a,node b){return a.p<b.p;} int find(int x) { if(x!=fa[x]) fa[x]=find(fa[x]); return fa[x]; } int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) scanf("%d %d %d",&e[i].v,&e[i].u,&e[i].p); for(int i=1;i<=n;i++) fa[i]=i; sort(e+1,e+1+m,cmp); int ans=0; for(int i=1;i<=m;i++) { int p=find(e[i].v),q=find(e[i].u); if(p!=q) { // printf("********\n"); fa[p]=fa[q]; ans+=e[i].p; } } printf("%d",ans); return 0; }
4.字符串哈希
#include<cstdio> #include<cstring> #include<algorithm> using std::sort; #define ull unsigned long long const int N=10010; const int M=1512; char map[M]; ull sum[N],hash[M]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",map+1); memset(hash,0,sizeof(hash)); int len=strlen(map+1); for(int j=1;j<=len;j++) hash[j]=hash[j-1]*31+(map[j-1]-'a'+1); sum[i]=hash[len]; } int ans=1; sort(sum+1,sum+1+n); for(int i=2;i<=n;i++) { if(sum[i]!=sum[i-1]) ans++; } printf("%d\n",ans); return 0; }
5.KMP字符串匹配
#include<cstdio> #include<cstring> const int N=1000010; char a[N],b[N]; int lena,lenb,next[N]; void init() { int j=0;next[1]=0; for(int i=2;i<=lenb;i++) { while(j&&b[j+1]!=b[i]) j=next[j]; if(b[j+1]==b[i]) j++; next[i]=j; } } void sovle() { int j=0; for(int i=1;i<=lena;i++) { while(j&&b[j+1]!=a[i]) j=next[j]; if(b[j+1]==a[i]) j++; if(j==lenb) printf("%d\n",i-lenb+1); } } int main() { scanf("%s %s",a+1,b+1); lena=strlen(a+1),lenb=strlen(b+1); init(); sovle(); for(int i=1;i<=lenb;i++) printf("%d ",next[i]); return 0; }
6.堆
#include<cstdio> #include<cstring> #include<queue> using namespace std; priority_queue<int,vector<int>,greater<int> >q; int main() { int n; scanf("%d",&n); int pd; for(int i=1;i<=n;i++) { scanf("%d",&pd); if(pd==1) { int v; scanf("%d",&v); q.push(v); } if(pd==2) { printf("%d\n",q.top()); } if(pd==3) { q.pop(); } } return 0; }
7.矩阵快速幂
#include<cstdio> #include<cstring> const long long N=112; long long res[N][N],tt[N][N]; long long n,m; const long long mod=1e9+7; inline void matrix(long long a[N][N],long long b[N][N]) { memset(tt,0,sizeof(tt)); for(long long i=1;i<=n;i++) for(long long j=1;j<=n;j++) for(long long k=1;k<=n;k++) tt[i][j]=( tt[i][j]+(long long)a[i][k]*b[k][j]%mod)%mod; for(long long i=1;i<=n;i++) for(long long j=1;j<=n;j++) a[i][j]=tt[i][j]; } long long a[N][N]; void j_poww(long long b) { for(long long i=1;i<=n;i++) for(long long j=1;j<=n;j++) scanf("%lld",&a[i][j]); memset(res,0,sizeof(res)); for(long long i=1;i<=n;i++) res[i][i]=1; while(b) { if(b&1) matrix(res,a); b>>=1; matrix(a,a); } } int main() { scanf("%lld %lld",&n,&m); j_poww(m); for(long long i=1;i<=n;i++,printf("\n")) for(long long j=1;j<=n;j++) printf("%lld ",res[i][j]); return 0; }
8.线性筛素数
#include<cstdio> #include<cstring> const int N=1e7+12; int prime[N],book[N]; int main() { int n; scanf("%d",&n); int tot=0; for(int i=2;i<=n;i++) { if(!book[i]) prime[++tot]=i; for(int j=1;j<=tot;j++) { if(i*prime[j]>n) break; book[i*prime[j]]=1; if(!i%prime[j]) break; } } for(int i=1;i<=tot;i++) printf("%d ",prime[i]); return 0; }
9.卢卡斯定理
#include<cstdio> #include<cstring> #define ll long long const int N=1e6+12; ll aa[N<<1]; ll p; inline ll max(ll a,ll b){if(a>=b)return a;return b;} inline ll poww(ll a,ll b) { ll ans=1; while(b) { if(b&1) ans=ans*a%p; b>>=1;a=a*a%p; } return ans; } ll C(ll n,ll m){ if(n<m) return 0; if(n<p) return aa[n]*poww(aa[m],p-2)%p*poww(aa[n-m],p-2)%p; return C(n/p,m/p)*C(n%p,m%p)%p; } int main() { int t; scanf("%d",&t); while(t--) { ll n,m; scanf("%lld %lld %lld",&n,&m,&p); memset(aa,0,sizeof(aa)); aa[0]=1; for(int i=1;i<=n+m;i++) aa[i]=aa[i-1]*i%p; ll ans=C(n+m,n); printf("%lld\n",ans); } return 0; } //C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p //C(m,m+n)
10.线性求逆元
#include<cstdio> #include<cstring> #define ll long long const int N=3e6+12; ll inv[N]; int main() { int n,p; scanf("%d %d",&n,&p); inv[1]=1; printf("1\n"); for(int i=2;i<=n;i++) inv[i]=(-(p/i)*inv[p%i])%p+p,printf("%lld\n",inv[i]); return 0; }
11.ST表
#include<cstdio> #include<cstring> const int N=1e5+12; int map[N]; int lg[N],f[N][27]; inline int max(int a,int b){if(a>=b) return a;return b;} inline int query(int l,int r) { int t=lg[r-l+1]; return max(f[l][t],f[r-(1<<t)+1][t]); } int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&map[i]); for(int i=1;i<=n;i++) f[i][0]=map[i]; for(int j=1;j<=21;j++) for(int i=1;i<=n-(1<<j-1);i++) f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]); lg[1]=0; for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1; int l,r; for(int i=1;i<=m;i++) { scanf("%d %d",&l,&r); printf("%d\n",query(l,r)); } return 0; }
12.文件(freopen,fclose)
#include<cstdio> int main() { freopen("div.in","r",stdin); freopen("div.out","w",stdout); fclose(stdin); fclose(stdout); return 0; }
13.匈牙利算法
#include<cstdio> #include<cstring> const int N=210; int map[N][N]; int book[N]; int tag[N]; int n,m; bool find(int x) { for(int i=1;i<=m;i++) { if(map[x][i]&&(!book[i])) { book[i]=1; if(!tag[i]||find(tag[i])) { tag[i]=x; return true; } } } return false; } int main() { scanf("%d %d",&n,&m); int p; for(int i=1;i<=n;i++) { while(true) { scanf("%d",&p); if(!p) break; else map[i][p]=1; } } int ans=0; for(int i=1;i<=n;i++) { memset(book,0,sizeof(book)); if(find(i)) ans++; } printf("%d",ans); return 0; }
14.强联通分量
#include<cstdio> #include<cstring> #include<algorithm> using std::min; const int N=100010; struct node{int next,to,from;}e[N]; int first[N]; int book[N]; int dfn[N],low[N],stack[N],cd[N]; int cnt=0; void insert(int v,int u) { e[++cnt].to=u;e[cnt].from=v;e[cnt].next=first[v];first[v]=cnt; } int tot=0,top=0,num=0; int size[N],color[N]; void tarjan(int x) { dfn[x]=low[x]=++tot; book[x]=1;stack[++top]=x; for(int i=first[x];i;i=e[i].next) { if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); else if(book[e[i].to]) low[x]=min(low[x],low[e[i].to]); } if(dfn[x]==low[x]) { ++num; while(stack[top]!=x) { book[stack[top]]=0; color[stack[top]]=num; size[num]++; top--; } book[x]=0; color[x]=num; size[num]++; top--; } } int main() { int n,m; scanf("%d %d",&n,&m); int v,u; for(int i=1;i<=m;i++) { scanf("%d %d",&v,&u); insert(v,u); } int ans=0; for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=num;i++) if(size[i]!=1) ans++; cnt=0; memset(first,0,sizeof(first)); for(int i=1;i<=m;i++) if(color[e[i].from]!=color[e[i].to]) cd[color[e[i].from]]++,insert(color[e[i].from],color[e[i].to]); ans=0; int aim; for(int i=1;i<=num;i++) if(!cd[i]) ans++,aim=i; if(ans!=1) printf("0"); else printf("%d\n",size[aim]); return 0; }
15.多重背包
#include<cstdio> #include<cstring> #include<algorithm> using std::max; const int N=217; int v[N],w[N],m[N]; int dp[200010]; int main() { int nv,n; scanf("%d %d",&n,&nv); for(int i=1;i<=n;i++) { scanf("%d %d %d",&v[i],&w[i],&m[i]); } for(int i=1;i<=n;i++) { if(m[i]==1) { for(int j=nv;j>=v[i];j--) dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } else if(m[i]>=1) { if(v[i]*m[i]>=nv) { for(int j=v[i];j<=nv;j++) dp[j]=max(dp[j],dp[j-v[j]]+w[i]); } else { int k=1; while(k<m[i]) { for(int j=nv;j>=v[i]*k;j--) dp[j]=max(dp[j],dp[j-v[i]*k]+w[i]*k); m[i]-=k; k<<=1; } if(m[i]>0) for(int j=nv;j>=v[i]*m[i];j--) dp[j]=max(dp[j],dp[j-v[i]*m[i]]+w[i]*m[i]); } } else { for(int j=v[i];j<=nv;j++) dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } } printf("%d",dp[nv]); return 0; }
16.拓扑排序
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=200010; struct node { int to,next; }e[N]; int first[N]; int in[N]; int cnt=0; int ans[N]; priority_queue<int>q; inline void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt; } int main() { int n,m; scanf("%d %d",&n,&m); int v,u; int tot=n+1; for(int i=1;i<=m;i++) { scanf("%d %d",&v,&u); insert(u,v);in[v]++; } for(int i=1;i<=n;i++) if(!in[i]) q.push(i); while(!q.empty()) { int p=q.top();q.pop(); ans[p]=--tot; for(int i=first[p];i;i=e[i].next) { --in[e[i].to]; if(!in[e[i].to]) q.push(e[i].to); } } for(int i=1;i<=n;i++) printf("%d ",ans[i]); return 0; }