模板整理(持续整理中)
二分
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid-1;
}
并查集
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=10005;
int f[maxn];
int n,m;
void init()
{
for(int i=1;i<=10000;i++)
f[i]=i;
}
int get(int x)
{
return f[x]=(x==f[x]? x:get(f[x]));
}
void merge(int x,int y)
{
f[get(x)]=get(y);
}
int main()
{
}
快速幂
//位运算版本
#include <iostream>
using namespace std;
int power(int a,int b,int p)
{
int ans=1%p;
for( ;b;b>>=1)
{
if(b&1)
ans=(long long)ans*a%p;
a=(long long)a*a%p;
}
return ans;
}
int main()
{
}
//递归版本
#include <iostream>
#include <cstdio>
using namespace std;
long long t,b,p,k,s,result=1;
int pow(int a,int b,int p)
{
if(b==0)
return 1;
if(b==1)
return a%p;
t=pow(a,b/2,p);
if(b>=2&&b%2==0)
return t*t%p;
if(b>=2&&b%2==1)
return t*t*a%p;
}
int main()
{
}
线性筛素数
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=10000005;
int v[maxn],p[maxn];//v代表v是不是质数,是的话为1,p为质数
void primes(int n)
{
int m=0;
memset(v,0,sizeof(v));
for(int i=2;i<=n;i++)
{
if(v[i]==0)
{
v[i]=i;
p[++m]=i;
}
for(int j=1;j<=m;j++)
{
if(p[j]>v[i]||p[j]>(n/i))
break;
v[i*p[j]]=p[j];
}
}
}
int main()
{
}
高精度(重载运算符)
struct bignum {
int l,h[1001];
inline void clear() {
memset(h,0,sizeof(h)), l = 0;
}
inline void arg() {
re int t = 1;
while(h[t] || t<l) {
if(h[t] < 0) h[t] += 10000, h[t+1] -= 1;
if(h[t] >= 10000) h[t+1] += h[t]/10000;
h[t++] %= 10000;
}
l = t-1;
}
inline void input(string s) {
clear();
re int p = 1, k = 1, t = 0;
for(re int i = 0; i < s.length(); ++i)
if(s[i] != '0') {t = i; break;}
for(re int i = s.length()-1; i >= t; --i)
if(k < 10000) h[p] += (s[i]-'0')*k, k *= 10;
else ++p, h[p] = s[i]-'0', k = 10;
l = p, arg();
}
inline void input(int w){
clear();
re int p = 1, k = 1;
while(w){
if(k < 10000) h[p] += (w%10)*k, k *= 10;
else ++p, h[p] = w%10, k = 10;
w /= 10;
}
l = p, arg();
}
inline void print() {
arg();
if(l<=1 && h[1]==0) {write(0); return;}
for(re int i = l; i >= 1; --i) {
if(i==l || h[i]>=1000) write(h[i]);
else {
re int l1 = 0, t = h[i];
while(t) t/=10,++l1;
while(++l1 <= 4) write(0);
if(h[i]) write(h[i]);
}
}
}
inline bignum operator + (const bignum b) const {
re bignum a = *this, c; c.clear();
c.l = max(a.l,b.l);
for(re int i = 1; i <= max(a.l,b.l); ++i)
c.h[i] = a.h[i]+b.h[i];
c.arg(); return c;
}
inline bignum operator * (const bignum b) const {
re bignum a = *this, c; c.clear(), c.l = a.l+b.l;
for(re int i = 1; i <= a.l; ++i) {
for(re int j = 1; j <= b.l; ++j)
c.h[i+j-1] += a.h[i]*b.h[j];
c.arg();///////////////////
}
c.arg(); return c;
}
inline bool operator < (bignum b) const {
bignum a = *this; a.arg(), b.arg();
if(a.l != b.l) return a.l < b.l;
for(re int i = a.l; i >= 1; --i)
if(a.h[i] < b.h[i]) return 1;
else if(a.h[i] > b.h[i]) return 0;
return 0;
}
inline bool operator > (bignum b) const {
bignum a = *this; a.arg(), b.arg();
if(a.l != b.l) return a.l > b.l;
for(re int i = a.l; i >= 1; --i)
if(a.h[i] > b.h[i]) return 1;
else if(a.h[i] < b.h[i]) return 0;
return 0;
}
}
邻接表存树,邻接表存图
const int N=100010,M=1000010;
int head[N],ver[M],edge[M],next[M],d[N],tot;
bool v[N];
void (int x,int y,int z)
{
ver[++tot]=y,edge[tot]=z,next[i]=head[x],head[x]=tot;
}
dfs
void dfs(int x){
v[x]=1;//记录点x被访问过,v是visit的缩写
for(int i=head[x];i;i=next[i]){
int y=ver[i];
if(v[y]) continue;
dfs(y);
}
}
dfs序
void dfs(int x){
a[++m]=x;
v[x]=1;
for(int i=head[x];i;i=next[i]){
int y=ver[i];
if(v[y]) continue;
dfs(y);
}
a[++m]=x;
}
求树的深度
void dfs(int x){
v[x]=1;
for(int i=head[x];i;i=next[i]){
int y=ver[i];
if(v[y]) continue;
d[y]=d[x]+1;
dfs(y);
}
}
树的重心
void dfs(int x){
v[x]=1;size[i]=1;
int max_part=0;
for(int i=head[x];i;i=next[i]){
int y=ver[i];
if(v[y]) continue;
dfs(y);
size[x]+=size[y];
max_part=max(max_part,size[y]);
}
max_part=max(max_part,n-size[x]);
if(max_part<ans){
ans=max_part;
pos=x;
}
}
bfs
void bfs()
{
memset(d,0,sizeof(d));
queue<int> q;
q.push(1);d[1]=1;
while(q.size()>0){
int x=q.front();
q.pop;
for(int i=head[x];i;next[i]){
int y=ver[i];
if(d[y]) continue;
d[y]=d[x]+1;
q.push(y);
}
}
}
单源最短路径
//spfa 慎用
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
const int N=100010,M=1000010;
int head[N],ver[M],edge[M],next[M],d[N];
bool v[N];
int n,m,s,tot;
queue <int> q;
void add(int x,int y,int z)
{
ver[++tot]=y,edge[tot]=z,next[tot]=head[x],head[x]=tot;
}
void spfa()
{
for(int i=1;i<=n;i++)
d[i]=2147483647;
memset(v,0,sizeof(v));
d[s]=0,v[s]=1;
q.push(s);
while(q.size())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=next[i])
{
int y=ver[i],z=edge[i];
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
if(!v[y]) q.push(y);
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
spfa();
for(int i=1;i<=n;i++)
cout<<d[i]<<" ";
return 0;
}
//dijkstra 常用
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
const int N=100010,M=1000010;
int head[N],ver[M],edge[M],next[M],d[N];
bool v[N];
int n,m,s,tot;
priority_queue <pair<int ,int> > q;
void add(int x,int y,int z)
{
ver[++tot]=y,edge[tot]=z,next[tot]=head[x],head[x]=tot;
}
void dijkstra()
{
for(int i=1;i<=n;i++)
d[i]=2147483647;
memset(v,0,sizeof(v));
d[s]=0;
q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second;
q.pop();
if(v[x]) continue;
v[x]=1;
for(int i=head[x];i;i=next[i])
{
int y=ver[i],z=edge[i];
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
q.push(make_pair(-d[y],y));
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
dijkstra();
for(int i=1;i<=n;i++)
cout<<d[i]<<" ";
return 0;
}
最小生成树
//Prim
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#define re register
#define ll long long
using namespace std;
int a[5005][5005],n,m,ans,d[5005];
bool v[5005];
void prim()
{
memset(d,0x3f,sizeof(d));
memset(v,0,sizeof(v));
d[1]=0;
for(re int i=1;i<=n;i++)
{
int x=0;
for(re int j=1;j<=n;j++)
if(!v[j]&&(x==0||d[x]>d[j])) x=j;
v[x]=1;
for(re int y=1;y<=n;y++)
if(!v[y]) d[y]=min(d[y],a[x][y]);
}
}
int main()
{
cin>>n>>m;
memset(a,0x3f,sizeof(a));
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
a[y][x]=a[x][y]=min(a[x][y],z);
}
prim();
for(int i=2;i<=n;i++) ans+=d[i];
cout<<ans<<endl;
return 0;
}
//克鲁斯卡尔
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#define re register
#define ll long long
using namespace std;
struct rec{int x,y,z;}edge[500010];
int fa[100010],n,m,ans;
bool operator <(rec a,rec b)
{
return a.z<b.z;
}
int get(int x)
{
return fa[x]=(x==fa[x])? x:get(fa[x]);
}
int main()
{
cin>>n>>m;
for(re int i=1;i<=m;i++)
cin>>edge[i].x>>edge[i].y>>edge[i].z;
sort(edge+1,edge+m+1);
for(re int i=1;i<=n;i++) fa[i]=i;
for(re int i=1;i<=m;i++)
{
int x=get(edge[i].x);
int y=get(edge[i].y);
if(x==y) continue;
fa[x]=y;
ans+=edge[i].z;
}
cout<<ans<<endl;
return 0;
}
树状数组
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m;
int a[500005],c[500005];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
for( ;x<=n;x+=lowbit(x)) c[x]+=y;
}
int ask(int x)
{
int ans=0;
for(;x;x-=lowbit(x)) ans+=c[x];
return ans;
}
int main()
{
}
求乘法逆元
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n,p;
long long inv[3000010];
int main()
{
cin>>n>>p;
inv[1]=1;
printf("1
");
for(int i=2;i<=n;i++)
{
inv[i]=(long long)(p-p/i)*inv[p%i]%p;
printf("%lld
",inv[i]);
}
return 0;
}
最近公共祖先
//LCA
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#define re register
#define ll long long
using namespace std;
const int size=50010;
int f[size][20],d[size],dist[size];
int ver[2*size],edge[2*size],next[2*size],head[size];
int T,n,m,tot,t;
queue <int>q;
void add(int x,int y,int z)
{
ver[++tot]=y,edge[tot]=z,next[tot]=head[x],head[x]=tot;
}
void bfs()
{
q.push(1);
d[1]=1;
while(q.size())
{
int x=q.front();
q.pop();
for(re int i=head[x];i;i=next[i]);
{
int y=ver[i],z=edge[i];
if(d[y]) continue
d[y]=d[x]+1;
dist[y]=dist[x]+z;
f[y][0]=x;
for(int j=1;j<=t;j++)
f[y][j]=f[y][f[y][j-1]][j-1];
q.push(y);
}
}
}
int lca(int x,int y)
{
if(d[x]>d[y]) swap(x,y);
for(re int i=t;i>=0;i--)
if(d[f[y][i]]>=d[x]) y=f[y][i];
if(x==y) return x;
for(re int i=t;i>=0;i--)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
cin>>T;
while(T--)
{
cin>>n>>m;
t=(int)(log(n)/log(2))+1;
for(re int i=1;i<=n;i++)
head[i]=d[i]=0;
tot=0;
for(re int i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
bfs();
for(re int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d
",dist[x]+dist[y]-2*dist[lca(x,y)]);
}
}
return 0;
}
矩阵快速幂
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1005;
const int mod=1000000007;
struct mat
{
long long m[maxn][maxn];
};
mat a,e;
long long n,p;
mat mul(mat x,mat y)
{
mat c;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
c.m[i][j]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
c.m[i][j]=(c.m[i][j]%mod+(x.m[i][k]*y.m[k][j])%mod)%mod;
}
}
return c;
}
mat pow(mat a,long long b)
{
mat ans=e;
while(b)
{
if(b&1)
ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
int main()
{
cin>>n>>p;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cin>>a.m[i][j];
}
for(int i=1;i<=n;i++)
e.m[i][i]=1;
mat s=pow(a,p);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
cout<<s.m[i][j]<<" ";
cout<<endl;
}
return 0;
}
nim游戏
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int t,n;
int main()
{
cin>>t;
while(t--)
{
int ans=0;
cin>>n;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
ans=ans^a;
}
if(ans)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}