NOIP的基本模板合集(1)
目录:
1.线性推逆元
2.线性筛素数
3.线性筛欧拉函数
4.质因数分解
5.gcd及exgcd
6.快速幂及快速乘
7.LCA算法(最近公共祖先)
8.树状数组
9.卢卡斯定理
10.高精度(加、减、压位乘法)
一.线性推逆元
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> using namespace std; long long n,p,inv[3000001]; int main() { scanf("%lld%lld",&n,&p); inv[1]=1; for(long long i=2;i<=n;i++) inv[i]=(p-p/i)*inv[p%i]%p; }
二.线性筛素数
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> using namespace std; int n,prime[100001],idx; bool notprime[100001]; int main() { scanf("%d",&n); for(int i=2;i<=n;i++) { if(notprime[i]==0) { prime[++idx]=i; } for(int j=1;j<=idx&&i*prime[j]<=n;j++) { notprime[i*prime[j]]=1; if(i%prime[j]==0) break; } } }
三.线性筛欧拉函数
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> using namespace std; int n,prime[100001],idx,phi[100001]; bool notprime[100001]; int main() { scanf("%d",&n); for(int i=2;i<=n;i++) { if(notprime[i]==0) { prime[++idx]=i; phi[i]=i-1; } for(int j=1;j<=idx&&i*prime[j]<=n;j++) { notprime[i*prime[j]]=1; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } }
四.质因数分解
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> using namespace std; int n,a[10001],idx; int main() { scanf("%d",&n); for(int i=2;i*i<=n;i++) { if(n%i==0) { a[++idx]=i; while(n%i==0) n/=i; } if(n!=1) a[++idx]=n; } return 0; }
五.gcd及exgcd
1.gcd
int gcd(int x,int y) { if(y==0) return x; return gcd(y,x%y); }
2.exgcd
int exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return a; } int cnt=exgcd(b,a%b,x,y); int idx=x; x=y; y=idx-a/b*y; return cnt; }
六.快速幂及快速乘
1.快速幂
int pow(int x,int y) { int ans=1; while(y) { if(y&1) ans=(ans*x)%mod; x=(x*x)%mod; y>>=1; } }
2.快速乘
int mul(int x,int y) { int ans=0; while(y) { if(y&1) ans=(ans+x)%mod; x=(x+x)%mod; y>>=1; } }
七.LCA算法(最近公公祖先)
1.树链剖分求LCA
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> using namespace std; #define N 500001 int n,m,s,to[N<<1],head[N],idx,nxt[N<<1],top[N],son[N],dep[N],siz[N],f[N]; void addedge(int x,int y) { to[++idx]=y; nxt[idx]=head[x]; head[x]=idx; } void dfs1(int x) { dep[x]=dep[f[x]]+1; siz[x]=1; for(int i=head[x];i;i=nxt[i]) if(f[to[i]]==0&&to[i]!=f[x]) { f[to[i]]=x; dfs1(to[i]); siz[x]+=siz[to[i]]; if(siz[son[x]]<siz[to[i]]) son[x]=to[i]; } } void dfs2(int x) { if(x==son[f[x]]) top[x]=top[f[x]]; else top[x]=x; for(int i=head[x];i;i=nxt[i]) if(to[i]!=f[x]) dfs2(to[i]); } int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) y=f[top[y]]; else x=f[top[x]]; } if(dep[x]>dep[y]) return y; else return x; } int main() { scanf("%d%d%d",&n,&m,&s); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } dfs1(s); dfs2(s); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } }
八.树状数组
1.单点加(单点修改)
int c[N]; int lowbit(int x) { return x&(-x); } void update(int x,int del) { while(x<=n) { c[x]+=del; x+=lowbit(x); } }
2.单点查询
int c[N]; int lowbit(int x) { return x&(-x); } int query(int x) { int ans=0; while(x) { ans+=c[x]; x-=lowbit(x); } return ans; }
九.卢卡斯定理(以洛谷模板为例)
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> using namespace std; #define N 100001 int n,m,t,p; long long fac[N]; long long mul(long long x,long long y,long long mod) { long long ans=0; while(y) { if(y&1) ans=(ans+x)%mod; x=(x+x)%mod; y>>=1; } return ans; } long long pow(long long x,long long y,long long mod) { long long ans=1; while(y) { if(y&1) ans=mul(ans,x,mod)%mod; x=mul(x,x,mod)%mod; y>>=1; } return ans; } long long C(long long x,long long y,long long mod) { if(y<x) return 0; if(x==y) return 1; return mul(mul(fac[y],pow(fac[x],mod-2,mod),mod),pow(fac[y-x],mod-2,mod),mod); } long long Lucas(long long x,long long y,long long mod) { if(x==0) return 1; return mul(Lucas(x/mod,y/mod,mod),C(x%mod,y%mod,mod),mod); } int main() { scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&p); fac[1]=1; for(int i=2;i<=p;i++) fac[i]=mul(fac[i-1],i,p); printf("%lld\n",Lucas(m,n+m,p)); } }
十.高精度(感谢ysy20021208提供模板)
高精加、减、压位乘法(重载运算符版)
#define mod 100000000 struct Num { long long num[N]; Num() {memset(num,0,sizeof(num));} Num operator + (const Num &a) const { Num ans;ans.num[0]=max(a.num[0],num[0]);long long tmp=0; for(int i=1;i<=ans.num[0];i++) ans.num[i]=num[i]+a.num[i]+tmp,tmp=ans.num[i]/mod,ans.num[i]%=mod; while(tmp) ans.num[++num[0]]=tmp%mod,tmp/=mod; return ans; } Num operator - (const Num &a) const { Num ans;ans.num[0]=num[0];long long tmp=0; for(int i=1;i<=ans.num[0];i++) { if(num[i]-tmp-a.num[i]<0) ans.num[i]=num[i]-tmp-a.num[i]+mod,tmp=1; else ans.num[i]=num[i]-tmp-a.num[i],tmp=0; } while(ans.num[ans.num[0]]==0) ans.num[0]--; return ans; } Num operator * (const Num &a) const { Num ans,tmp;long long tmp1=0,tmp2; for(int i=1;i<=a.num[0];i++) { tmp2=a.num[i],tmp.num[0]=i-1,tmp1=0,tmp.num[tmp.num[0]]=0; for(int j=1;j<=num[0];j++) { tmp.num[++tmp.num[0]]=num[j]*tmp2+tmp1; tmp1=tmp.num[tmp.num[0]]/mod,tmp.num[tmp.num[0]]%=mod; } while(tmp1) tmp.num[++tmp.num[0]]=tmp1%mod,tmp1/=mod; ans=ans+tmp;return ans; } } Num operator ^ (const int &a) const { Num ans,x;int y=a;ans.num[0]=ans.num[1]=1; for(int i=0;i<=num[0];i++) x.num[i]=num[i]; while(y) {if(y&1) ans=ans*x;x=x*x,y>>=1;} return ans; } };