OI常用模板
long long qpow(long long a,long long b,int mod)
{
long long res=;
while (b)
{
if (b&) res=res*a%mod;
a=a*a%mod;
b>>=;
}
return res%mod;
}
快速幂
const int mod1=;
const int mod2=;
const int mod3=;
bool show[mod3];
int hash(string a)
{
long long val=;
int ha1=,ha2=;
int len=a.length();
for(register int i=len-;i>-;i--)
{
ha1+=a[i]*val;
ha1%=mod1;
ha2+=a[i]*val;
ha2%=mod2;
val*=;
if(val > ) val=;
}
return (long long)ha1*ha2%mod3;
}
字符串哈希
int k,n,m,cnt,sum,ai,bi,ci,head[],dis[],vis[];
struct Edge
{
int v,w,next;
}e[];
void add(int u,int v,int w)
{
e[++k].v=v;
e[k].w=w;
e[k].next=head[u];
head[u]=k;
}
typedef pair <int,int> pii;
priority_queue <pii,vector<pii>,greater<pii> > q;
int Prim()
{
memset(dis,,sizeof(dis));
memset(head,-,sizeof(head));
dis[]=;
q.push(make_pair(,));
while(!q.empty()&&cnt<n)
{
int d=q.top().first,u=q.top().second;
q.pop();
if(vis[u]) continue;
cnt++;
sum+=d;
vis[u]=;
for(R i=head[u];i!=-;i=e[i].next)
if(e[i].w<dis[e[i].v])
dis[e[i].v]=e[i].w,q.push(make_pair(dis[e[i].v],e[i].v));
}
if (cnt==n) return sum;
return -;
Prim
struct Edge
{
int x,y,z;
}e[];
int n,m,u,v,fu,fv,cnt,ans;
int fa[];
bool cmp(Edge a,Edge b){return a.z < b.z || (a.z==b.z && a.x<b.x);}
int find(int x){return x == fa[x]?x:fa[x]=find(fa[x]);}
void kruskal()
{
for(int i=;i<=m;i++) fa[i] = i;
for(int i=;i<=n;i++)
{
u = e[i].x;
v = e[i].y;
fu = find(u);
fv = find(v);
if(fu != fv)
{
fa[fu] = fv;
ans += e[i].z;
cnt++;
}
if(cnt == m-) break;
}
if (ans) return ans;
return -'
}
Kruskal(最后return,";"写成"'"了,请自行改过来)
#ifndef DS
#define DS
template <unsigned const long long maxn=>
class i_Ds
{
typedef long long X;
X s[maxn],height[maxn];
typedef X inte;
public:
void init(){for (inte i=;i<maxn;i++) s[i]=i,height[i]=;}
i_Ds(){init();}
X find(X x) {if (x!=s[x]) s[x]=find(s[x]);return s[x];}
void _union(X x,X y)
{
x=find(x);y=find(y);
if (height[x]==height[y]) height[x]++,s[y]=x;
else if(height[x]<height[y]) s[x]=y;
else s[y]=x;
}
inte js(inte b,inte n) {inte ans=;for (inte i=b;i<n;i++)if (s[i]==i) ++ans;return ans;}
inte js(const inte n=maxn){inte ans=;for (inte i=;i<n;i++)if (s[i]==i) ++ans;return ans;}
};
#endif
并查集(路径压缩+按秩合并)
int prime[maxn];
int visit[maxn];
void Prime()
{
memset(visit,,sizeof visit);
memset(prime,,sizeof prime);
for (int i=;i<=maxn;i++)
{
if (!visit[i]) prime[++prime[]]=i;
for (int j=;j<=prime[]&&i*prime[j]<=maxn;j++)
{
visit[i*prime[j]]=;
if ((!i%prime[j])) break;
}
}
}
线性筛素数(欧拉筛)
void qsort(int a[],int l,int r)
{
int i=l,j=r,mid=a[(l+r)/];
do
{
while (a[i]<mid) i++;
while (a[j]>mid) j--;
if (i<=j)
{
int tmp=a[i];a[i]=a[j];a[j]=tmp;
i++;j--;
}
}while(i<=j);
if (l<j) qsort(a,l,j);
if (i<r) qsort(a,i,r);
}
快排
//用洛谷P3865做示范
#include<cstdio>
#define max(a,b) (a>b?a:b)
using namespace std;
int data[]={};
int init[]={-};
int st[][]={};
int main()
{
int N=,M=;
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++)
{
scanf("%d",&data[i]);
init[i]=init[i/]+;
}
for(int i=;i<=N;i++) //init begin.
st[i][]=data[i];
for(int i=;i<=init[N];i++)
for(int j=;j+(<<i)-<=N;j++)
st[j][i]=max(st[j][i-],st[j+(<<(i-))][i-]);//init end.
int Left=,Right=;
while(M--)
{
scanf("%d%d",&Left,&Right);
int Length=init[Right-Left+];
printf("%d\n",max(st[Left][Length],st[Right-(<<(Length))+][Length]));
}
return ;
}
ST表
if (所有石子个数异或得到的数字==) cout<<"先手必败“;
else cout<<"先手必胜“;
Nim游戏
void exgcd(int a,int b,int& x,int& y)
{
if (!b){x=,y=;return ;}
exgcd(b,a%b);
int t=x;
x=y,y=t-a/b*y;
}
Exgcd
//前置exgcd
int inv(int k,int p)
{
int x,y;
exgcd(k,p,x,y);
return (x%p+p)%p;
}
乘法逆元
const int N = ; //设置数组的大小
bool line[N][N]; //记录连接x和y的边,如果i和j之间有边则为1,否则为0
int result[N]; //记录当前与y节点相连的x的节点:i未加入匹配时为link[i]==0
bool used[N]; //记录y中节点是否使用
int k, m, n;
bool found(int x)
{
for (int i = ; i <= n; i++)
{
if (line[x][i] && !used[i])
{
used[i] = true;
if (result[i] == || found(result[i]))
{
result[i] = x;
return true;
}
}
}
return false;
}
int main()
{
int x, y;
printf("请输入相连边的数量k:\n");
while (scanf("%d", &k) && k)
{
printf("请输入二分图中x和y中点的数目:\n");
scanf("%d %d", &m, &n);
memset(line, , sizeof(line));
memset(result, , sizeof(result));
for (int i = ; i < k; i++)
{
printf("请输入相连边的两个点:\n");
scanf("%d %d", &x, &y);
line[x][y] = ;
}
int sum = ;
for (int i = ; i <= m; i++)
{
memset(used, , sizeof(used));
if (found(i)) sum++;
}
printf("%d\n", sum);
}
return ;
}
[邻接矩阵]匈牙利算法
//P3379示范
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Edge
{
int Length,Next;
}ed[];
int start[],tot;
void Add_Edge(int x,int y)
{
ed[++tot].Length=y;
ed[tot].Next=start[x];
start[x]=tot;
}
int depth[], f[][], lg[];
void dfs(int now,int pre)
{
f[now][]=pre;
depth[now]=depth[pre]+;
for (int i=;i<=lg[depth[now]];++i)
f[now][i]=f[f[now][i-]][i-];
for (int i=start[now];i!=;i=ed[i].Next)
if(ed[i].Length!=pre) dfs(ed[i].Length,now);
}
int LCA(int x, int y)
{
if (depth[x]<depth[y]) swap(x,y);
while (depth[x]>depth[y])
x=f[x][lg[depth[x]-depth[y]]-];
if (x==y) return x;
for (int k=lg[depth[x]]-;k>=;--k)
if (f[x][k]!=f[y][k])
x=f[x][k],y=f[y][k];
return f[x][];
}
int main()
{
int n,m,s;
scanf("%d%d%d", &n, &m, &s);
for (int i=;i<=n-;++i)
{
int x,y;
scanf("%d%d",&x,&y);
Add_Edge(x,y);
Add_Edge(y,x);
}
for(int i=;i<=n;++i)
lg[i]=lg[i-]+(<<lg[i-]==i);
dfs(s,);
for (int i=;i<=m;++i)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",LCA(x,y));
}
return ;
}
LCA
#include<iostream>
#include<cstring>
#innclude<cmath>
struct Trie
{
int ch[maxn][maxsize];
int val[maxn];
int sz;
Trie()
{
sz=;
val[]=;
memset(ch[],,sizeof ch[]);
}
void clear()
{
sz=;
val[]=;
memset(ch[],,sizeof ch[]);
}
int idx(char c){return c-'a';}
void insert(const char *s,int v=)
{
int u=,n=strlen(s);
for (int i=;i<n;i++)
{
int c=idx(s[i]);
if (ch[u][c]==)
{
memset(ch[sz],,sizeof ch[sz]);
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
int find(const char *s)
{
int u=,n=strlen(s);
for (int i=;i<n;i++)
{
int c=idx(s[i]);
if (ch[u][c]==) return -;
u=ch[u][c];
}
return val[u];
}
void del(const char *s)
{
int u=,n=strlen(s);
for (int i=;i<n;i++)
{
int c=idx(s[i]);
if (ch[u][c]==) return ;
u=ch[u][c];
}
val[u]=;
}
};
Trie
struct point
{
int hao;
ll dis;
bool friend operator <(point a,point b){return a.dis>b.dis;}
};
priority_queue<point>q;
void dij()
{
point st;
st.hao=s;
st.dis=;
q.push(st);
int has=;
while ((has!=n)&&(!q.empty()))
{
point now=q.top();
q.pop();
if (vis[now.hao]) continue;
has++;
vis[now.hao]=;
dis[now.hao]=now.dis;
for (int i=head[now.hao];i;i=bian[i].nxt)
{
int y=bian[i].to;
if (!vis[y])
{
point last;
last.hao=y;
last.dis=now.dis+bian[i].val;
q.push(last);
}
}
}
}
Dijkstra+堆优化
//初始化
for (i=;i<=n;i++)
for (j=;j<=n;j++)
e[i][j]=(i==j)?:inf;
//核心
for(k=;k<=n;k++)
for(i=;i<=n;i++)
for(j=;j<=n;j++)
e[i][j]=max(e[i][j],e[i][k]+e[k][j]);
Floyd
int Kmp(char* s, char* p)
{
int i=,j=;
int sLen=strlen(s);
int pLen=strlen(p);
while (i<sLen&&j<pLen)
{
if (j==-||s[i]==p[j]) i++,j++;
else j=next[j];
}
if (j==pLen) return i-j;
else return -;
}
KMP
char s[];
char s_new[]
int p[];
int Init()
{
int len=strlen(s);
s_new[]='$';
s_new[]='#';
int j=;
for(int i=;i<len;i++)
{
s_new[j++]=s[i];
s_new[j++]='#';
}
s_new[j]='\0';
return j;
}
int Manacher()
{
int len=Init();
int max_len=-;
int id;
int mx=;
for(int i=;i<=len;i++)
{
if(i<mx)
p[i]=min(p[*id-i],mx-i);
else p[i]=;
while (s_new[i-p[i]]==s_new[i+p[i]]) p[i]++;
if(mx<i+p[i]) id=i,mx=i+p[i];
max_len=max(max_len,p[i]-);
}
return max_len;
}
Manacher(马拉车)
//最小表示法
int getMin(char *str)
{
int i=,j=,k=;
int slen=strlen(str);
while (i<slen&&j<slen&&k<slen)
{
int tmp=str[(i+k)%slen]-str[(j+k)%slen];
if (tmp==) k++;
else
{
if (tmp>) i=i+k+;
else j=j+k+;
if (j==i) j++;
k=;
}
}
return min(i,j);
}
//最大表示法
int getMax(char *str)
{
int i=,j=,k=;
int slen=strlen(str);
while (i<slen&&j<slen&&k<slen)
{
int tmp=str[(i+k)%slen]-str[(j+k)%slen];
if (tmp==) k++;
else
{
if (tmp>) j=j+k+;
else i=i+k+;
if (i==j) j++;
k=;
}
}
return min(i,j);
}
最小(大)表示法
//hdu2222为例
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+;
const int MAX=;
int cnt;
struct node
{
node *next[];
node *fail;
int sum;
};
node *root;
char key[];
node *q[MAX];
int head,tail;
node *newnode;
char pattern[maxn];
int N;
void Insert(char *s)
{
node *p = root;
for(int i = ; s[i]; i++)
{
int x = s[i] - 'a';
if(p->next[x] == NULL)
{
newnode=(struct node *)malloc(sizeof(struct node));
for(int j=;j<;j++) newnode->next[j] = ;
newnode->sum = ;newnode->fail = ;
p->next[x]=newnode;
}
p = p->next[x];
}
p->sum++;
}
void build_fail_pointer()
{
head = ;
tail = ;
q[head] = root;
node *p;
node *temp;
while(head < tail)
{
temp = q[head++];
for(int i = ; i <= ; i++)
{
if(temp->next[i])
{
if(temp == root)
{
temp->next[i]->fail = root;
}
else
{
p = temp->fail;
while(p)
{
if(p->next[i])
{
temp->next[i]->fail = p->next[i];
break;
}
p = p->fail;
}
if(p == NULL) temp->next[i]->fail = root;
}
q[tail++] = temp->next[i];
}
}
}
}
void AC(char *ch)
{
node *p = root;
int len = strlen(ch);
for(int i = ; i < len; i++)
{
int x = ch[i] - 'a';
while(!p->next[x] && p != root) p = p->fail;
p = p->next[x];
if(!p) p = root;
node *temp = p;
while(temp != root)
{
if(temp->sum >= )
{
cnt += temp->sum;
temp->sum = -;
}
else break;
temp = temp->fail;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
root=(struct node *)malloc(sizeof(struct node));
for(int j=;j<;j++) root->next[j] = ;
root->fail = ;
root->sum = ;
scanf("%d",&N);
getchar();
for(int i = ; i <= N; i++)
{
gets(key);
Insert(key);
}
gets(pattern);
cnt = ;
build_fail_pointer();
AC(pattern);
printf("%d\n",cnt);
}
return ;
}
AC自动机
for(int i=;i<=n;i++)
for(int j=m;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
0-1背包
for(int i=;i<=n;i++)
for(int j=w[i];j<=m;j++)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
完全背包
for(int i=;i<=n;i++)
{
int x,y,s,t=;
scanf("%d%d%d",&x,&y,&s); //重量,价值,数量
while (s>=t){v[++n1]=x*t;w[n1]=y*t;s-=t;t*=;}
v[++n1]=x*s;
w[n1]=y*s;
}
for(int i=;i<=n1;i++)
for(int j=m;j>=v[i];j--)
dp[j]=max(dp[j],f[dp-v[i]]+w[i]);
多重背包(二进制分组)
//洛谷P1855为例
#include<cstdio>
#include<iostream>
using namespace std;
int n,M,T,dp[][];
int m[],t[];
int main()
{
scanf("%d%d%d",&n,&M,&T);
for(int i=;i<=n;i++)
{
scanf("%d%d",&m[i],&t[i]);
for(int j=M;j>=m[i];j--)
for(int k=T;k>=t[i];k--)
dp[j][k]=max(dp[j][k],dp[j-m[i]][k-t[i]]+);
}
printf("%d",dp[M][T]);
return ;
}
二维费用背包
//洛谷P1757为例
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 100000
#define sc scanf
#define pr printf
#define re register
using namespace std;
int n,m,ans,mm;
int tong[][],f[maxn],w[maxn],v[maxn],c[maxn],num[maxn];
int main()
{
bool cp=true;
cin>>m>>n;
if (m!=||n!=) cp=false;
for(re int i=;i<=n;i++)
{
cin>>w[i]>>v[i]>>c[i];
if (w[i]!=||v[i]!=||c[i]!=i) cp=false;
num[c[i]]++;
if(num[c[i]]==)
mm++;
tong[c[i]][num[c[i]]]=i;
}
if (cp){cout<<;return ;}
for (int k=;k<=mm;k++)
for (int j=m;j>=;j--)
for (int i=;i<=num[k];i++)
if(j-w[tong[k][i]]>)
f[j]=max(f[j],f[j-w[tong[k][i]]]+v[tong[k][i]]);
cout<<f[m];
return ;
}
分组背包
//以"NOIP2006金明的预算方案"为例
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m;
int f[],h[];
struct node{int v,p,q;}a[];
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&a[i].v,&a[i].p,&a[i].q);
a[i].p*=a[i].v;
}
for(int i=;i<=m;i++)
if(!a[i].q)
{
for(int j=;j<a[i].v;j++)
h[j]=;
for(int j=a[i].v;j<=n;j++)
h[j]=f[j-a[i].v]+a[i].p;
for(int j=;j<=m;j++)
if(a[j].q==i)
for(int k=n;k>=a[i].v+a[j].v;k--)
h[k]=max(h[k],h[k-a[j].v]+a[j].p);
for(int j=a[i].v;j<=n;j++)
f[j]=max(f[j],h[j]);
}
printf("%d\n",f[n]);
return ;
}
有依赖的背包
//它为何在这?因为SPFA本来在前面,然后代码失效,只好搬到这
int dis[MAXN];
bool vis[MAXN];
void SPFA(int s)
{
for(int i=;i<=MAXN;i++){dis[i]=INF;vis[i]=true;}
dis[s]=;
queue<int> q;
q.push(s);
vis[s]=false;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=true;
for(int i=head[u];~i;i=ed[i].next)
{
int v=ed[i].to;
if(dis[u]+ed[i].w<dis[v])
{
dis[v]=dis[u]+ed[i].w;
if(vis[v]){q.push(v);vis[v]=false;}
}
}
}
}
SPFA
#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
using namespace std;
struct Wint:vector<int>
{
Wint(int n=)
{
push_back(n);
check();
}
Wint& check()
{
while(!empty()&&!back())pop_back();
if(empty())return *this;
for(int i=; i<size(); ++i)
{
(*this)[i]+=(*this)[i-]/;
(*this)[i-]%=;
}
while(back()>=)
{
push_back(back()/);
(*this)[size()-]%=;
}
return *this;
}
};
istream& operator>>(istream &is,Wint &n)
{
string s;
is>>s;
n.clear();
for(int i=s.size()-; i>=; --i)n.push_back(s[i]-'');
return is;
}
ostream& operator<<(ostream &os,const Wint &n)
{
if(n.empty())os<<;
for(int i=n.size()-; i>=; --i)os<<n[i];
return os;
}
bool operator!=(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return ;
for(int i=a.size()-; i>=; --i)
if(a[i]!=b[i])return ;
return ;
}
bool operator==(const Wint &a,const Wint &b){return !(a!=b);}
bool operator<(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return a.size()<b.size();
for(int i=a.size()-; i>=; --i)
if(a[i]!=b[i])return a[i]<b[i];
return ;
}
bool operator>(const Wint &a,const Wint &b){return b<a;}
bool operator<=(const Wint &a,const Wint &b){return !(a>b);}
bool operator>=(const Wint &a,const Wint &b){return !(a<b);}
Wint& operator+=(Wint &a,const Wint &b)
{
if(a.size()<b.size())a.resize(b.size());
for(int i=; i!=b.size(); ++i)a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,const Wint &b)
{
return a+=b;
}
Wint& operator-=(Wint &a,Wint b)
{
if(a<b) swap(a,b);
for(int i=; i!=b.size(); a[i]-=b[i],++i)
if(a[i]<b[i])
{
int j=i+;
while(!a[j])++j;
while(j>i)
{
--a[j];
a[--j]+=;
}
}
return a.check();
}
Wint operator-(Wint a,const Wint &b){return a-=b;}
Wint operator*(const Wint &a,const Wint &b)
{
Wint n;
n.assign(a.size()+b.size()-,);
for(int i=; i!=a.size(); ++i)
for(int j=; j!=b.size(); ++j)
n[i+j]+=a[i]*b[j];
return n.check();
}
Wint& operator*=(Wint &a,const Wint &b){return a=a*b;}
Wint divmod(Wint &a,const Wint &b)
{
Wint ans;
for(int t=a.size()-b.size(); a>=b; --t)
{
Wint d;
d.assign(t+,);
d.back()=;
Wint c=b*d;
while(a>=c)
{
a-=c;
ans+=d;
}
}
return ans;
}
Wint operator/(Wint a,const Wint &b){return divmod(a,b);}
Wint& operator/=(Wint &a,const Wint &b){return a=a/b;}
Wint& operator%=(Wint &a,const Wint &b){divmod(a,b);return a;}
Wint operator%(Wint a,const Wint &b){return a%=b;}
Wint pow(const Wint &n,const Wint &k)
{
if(k.empty())return ;
if(k==)return n*n;
if(k.back()%)return n*pow(n,k-);
return pow(pow(n,k/),);
}
百度百科-高精
namespace IO
{
template<typename T>
inline void read(T &x)
{
x=;
int f=;
char ch=getchar();
while(!(ch>=''&&ch<='')){f|=(ch=='-');ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+(ch^);ch=getchar();}
x=f?-x:x;
}
template<typename T>
inline void write(T x)
{
if(x<) {putchar('-');x=-x;}
if(x>=) write(x/);
putchar(x%+'');
}
}
快读快输
//效果好
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
//效果不太好
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
极致优化
void getphi()
{
int i,j;
phi[]=;
for (i=;i<=N;i++)
{
if (!mark[i]) {prime[++tot]=i;phi[i]=i-;}
for (j=;j<=tot;j++)
{
if(i*prime[j]>N) break;
mark[i*prime[j]]=;
if (i%prime[j]==){phi[i*prime[j]]=phi[i]*prime[j];break; }
else phi[i*prime[j]]=phi[i]*(prime[j]-);
}
}
}
线性筛欧拉函数
#include<cstdio>
struct node
{
int data;
node* lchild;
node* rchild;
};
node* newNode(int v)
{
node* Node=new node;
Node->data=v;
Node->lchild=Node->rchild=NULL;
return Node;
}
void insert(node* &root,int x)
{
if(root==NULL){root=newNode(x);return;}
if(x==root->data) return;
else if(x<root->data) insert(root->lchild,x);
else insert(root -> rchild,x);
}
node* Create(int data[],int n)
{
node* root=NULL;
for(int i=;i<n;i++) insert(root,data[i]);
return root;
}
node* findMax(node* root)
{
while(root->rchild!=NULL){root=root->rchild;}
return root;
}
node* findMin(node* root)
{
while(root->lchild!=NULL) root=root->lchild;
return root;
}
void deleteNode(node* &root,int x){
if(root == NULL) return;
if(root->data==x)
{
if(root->lchild==NULL&&root->rchild==NULL) root=NULL;
else if(root->lchild!=NULL)
{
node* pre=findMax(root->lchild);
root->data=pre->data;
deleteNode(root->lchild,pre->data);
}
else
{
node* post=findMin(root->rchild);
root->data=post->data;
deleteNode(root->rchild,post->data);
}
}
else if (root->data>x) deleteNode(root->lchild,x);
else deleteNode(root->rchild,x);
}
BST(二叉搜索树&二叉排序树)
#include<iostream>
using namespace std;
typedef unsigned long long ull;
ull fact[]={,,,,,,,,,,,,,,};
int A[];
int main()
{
int rank=,s;
int N;
cin>>N;
for (int i=;i<N;i++) cin>>A[i];
for(int i=;i<=N;i++)
{
int s=;
for (int j=i+;j<=N;j++) s+=(A[j]<A[i]);
rank+=s*fact[N-i];
}
cout<<rank;
return ;
typedef unsigned long long ull;
const ull fact[]={,,,,,,,,,,,,,,,};
ull Cantor(int n,int a[])
{
ull ans=;
for (int i=;i<n;i++)
{
int x=;
for(int j=i+;j<n;j++)
if (a[j]<a[i]) ++x;
ans+=x*fact[n-i-];
}
return ans+;
}
康托展开
typedef unsigned long long ull;
const ull fac[]={,,,,,,,,,,,,,,,};
void CantorReverse(long long r,int len,int a[]) //康托展开逆运算,结果在a中
{
r--;
int vis[]={};
for(int i=;i<=len;i++)
{
long long tp=r/fac[len-i];
r-=tp*fac[len-i];
int j;
for(j=;j<=len;j++)
if(!vis[j]){if(!tp) break;--tp;}
vis[j]=;
a[i]=j;
}
}
康托展开逆运算
int binarySearch(int list[],int left,int right,int number)
{
if(list==NULL) return -;
int index=;
int mid=(right+left)/;
if(left>right)
return -;
if(number==list[mid])
{
index=mid;
return index;
}
else if(number>list[mid]) binarySearch(list,mid+,right,number);
else binarySearch(list,left,mid-,number);
}
二分查找(递归)
int binarySearch(int list[],int left,int right,int number)
{
if(list==NULL) return -;
while(left<right)
{
int mid=(right+left)/;
if (list[mid] == number) return mid;
else if (number > list[mid]) left=mid+;
else if (number < list[mid]) right=mid-;
}
return -;
}
二分查找(循环)
int sum[*+];
int lowbit(int x) {return x&(-x);}
inline void add(int x,int c){while (x<=n) {sum[x]+=c;x+=lowbit(x);}}
inline int query(int x)
{
int ans=;
while (x>)
{
ans+=sum[x];
x-=lowbit(x);
}
return ans;
}
inline void Make(int a[],const int n)
{
int pre[N];
pre[]=a[];
for (int i=;i<=n;i++) pre[i]=pre[i-]+a[i];
for (int i=;i<=n;i++) sum[i]=pre[i]-pre[i-lowbit(i)];
}
inline int SectionSum(int x,int y){return query(y)-query(x-);}
树状数组
dp[]=;
for (int =;i<n;i++)
{
dp[i]=;
for (int j=;j<i;j++)
if (x[i]>x[j]&&dp[j]+>dp[i]) dp[i]=dp[j]+;
}
for (int i=max_len=;i<n;i++)
max_len=max(max_len,dp[i]);
LIS
int len_a=a.size(),len_b=b.size();
for(int i=;i<len_a;i++)
for(int j=;j<len_b;j++)
if (a.at(i)==b.at(j)) dp[i+][j+]=dp[i][j]+;
else dp[i+][j+]=max(dp[i+][j],dp[i][j+]);
cout<<dp[len_a][len_b];
LCS
//i1,i2为两序列,n,m为序列长度
for (int a=;a<=m;a++)
{
int Max();
for (int b=;b<=n;b++)
{
if (i1[a]>i2[b]&&dp[a-][b]>Max) Max=dp[a-][b];
if (i1[a]!=i2[b]) dp[a][b]=dp[a-][b];
if (i1[a]==i2[b]) dp[a][b]=Max+;
}
}
LCIS
大根堆:priority_queue<DataType> Name; 小根堆:priority_queue<DataType,vector<DataType>,greater<DataType> > Name;
STL优先队列模板
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=;
const int INF=0x3f3f3f3f;
typedef long long LL;
struct edge
{
int en,len,next;
}E[maxn*maxn];
struct node
{
int id,len;
node(int id1=,int len1=){id=id1;len=len1;}
friend bool operator<(const node& x,const node& y){return x.len>y.len;}
};
int head[maxn],num;
int n,m;
int vis[maxn],dis[maxn];
void init(){memset(head,-,sizeof(head));num=;}
void add_edge(int st,int en,int len)
{
E[num].en=en;
E[num].len=len;
E[num].next=head[st];
head[st]=num++;
}
void Dijkstra(int st)
{
for (int i=;i<=n;i++) vis[i]=,dis[i]=INF;
dis[st]=;
priority_queue<node> Q;
Q.push(node(st,));
while (!q.empty())
{
node now=q.top();
Q.pop();
if (vis[now.id]==) continue;
vis[now.id]=;
for (int i=head[now.id];i!=-;i=E[i].next)
{
int en=E[i].en;
int len=E[i].len;
if (!vis[en]&&(dis[en]>dis[now.id]+len))
{
dis[en]=dis[now.id]+len;
Q.push(node(en,dis[en]));
}
}
}
}
int main()
{
init(); return ;
}
Dij-全代码版
#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int maxx=,maxn=;
struct Edge
{
int y,to,next;
}e[maxn],e1[maxn];
int head[maxx],tot,head1[maxx],cnt;
int n,m,dis[maxx],S,T,K,vis[maxx];
inline void add(int x,int y,int z){e[++tot]=(Edge){y,z,head[x]};head[x]=tot;}
inline void add1(int x,int y,int z){e1[++cnt]=(Edge){y,z,head1[x]};head1[x]=cnt;}
priority_queue<pair<int,int> >q; //大根堆插入相反数
inline void dijkstra() //处理估价函数
{
memset(dis,0x3f,sizeof dis);
memset(vis,-,sizeof vis);
dis[T]=;
q.push(make_pair(,T));
while (!q.empty())
{
int x=q.top().second;
q.pop();
if (!vis[x])continue;
vis[x]=;
for (int i=head1[x];i;i=e1[i].next)
{
int y=e1[i].y;
if (dis[y]>dis[x]+e1[i].to)
{
dis[y]=dis[x]+e1[i].to;
q.push(make_pair(-dis[y],y));
}
}
}
}
inline void A_star()
{
if (dis[S]==dis[]){puts("-1");return;}
if (S==T) K++;
memset(vis,,sizeof vis);
q.push(make_pair(-dis[S],S));
while (q.size())
{
int x=q.top().second,d=-q.top().first-dis[x];
q.pop();
vis[x]++;
if (vis[T]==K){printf("%d",d);return;}
for (int i=head[x];i;i=e[i].next)
{
int y=e[i].y;
if (vis[y]!=K) q.push(make_pair(-d-e[i].to-dis[y],y));
}
}
puts("-1");
}
int main()
{
cin>>n>>m;
for(int i=;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z); add1(y,x,z);
}
cin>>S>>T>>K;
dijkstra();
A_star();
return ;
}
K短路
template<typename T>
inline void Radix_Sort(T* a,T* b)
{
register const int n=b-a;
size_t size_of_type=sizeof(T);
size_t num_of_buc=size_of_type>>;
unsigned** r=new unsigned *[num_of_buc];
register int i,k;
for(i=; i<num_of_buc;i++)
r[i]=new unsigned [0x10000],memset(r[i],,0x10000*sizeof(unsigned));
register unsigned short tmp_us;
register T *j,*tar;
for (k=;k<num_of_buc;++k)
for (j=a+,tar=a++n;j!=tar;++j)
tmp_us=*(((unsigned short*)j)+k),++r[k][tmp_us];
for (k=;k<num_of_buc;++k)
for (i=;i<=0xffff;++i)
r[k][i]+=r[k][i-];
for (k=;k<num_of_buc;k+=0x2)
{
i=k;
for (j=a+n;j!=a;--j)
tmp_us=*(((unsigned short*)j)+i),b[r[i][tmp_us]--]=*j;
i|=;
if (i==num_of_buc) break;
for (j=b+n;j!=b;--j)
tmp_us=*(((unsigned short*)j)+i),a[r[i][tmp_us]--]=*j;
}
for(int i=;i<num_of_buc;i++) delete[] r[i];
delete [] r;
}
基数排序(位运算优化)
void us(int a[],const int n)
{
int t[n];
copy(a,a+n,t);
sort(t+,t+n+);
m=unique(t+,t+n+)-t-;
for (int i=;i<=n;i++)
a[i]=lower_bound(t+,t+m+,a[i])-t;
}
离散化
#include<iostream>
#include<algorithm>
using namespace std;
const int N=;
int a[N],rr[N],ans;
void msort(int l,int r)
{
if (r-l>)
{
int mid=(l+r)>>;
msort(l,mid);
msort(mid,r);
int x=l,y=mid,z=l;
while (x<mid||y<r)
{
if (y>=r||(x<mid&&a[x]<=a[y])) rr[z++]=a[x++];
else rr[z++]=a[y++],ans+=mid-x;
}
for (int i=l;i<r;i++) a[i]=rr[i];
}
}
int main()
{
int n;
cin>>n;
for (int i=;i<n;i++) cin>>a[i];
msort(,n);
cout<<ans;
return ;
}
求逆序对(归并排序)
void MakeInv(int n,int p)
{
inv[]=;
for(int i=;i<=n;i++)
inv[i]=1ll*(p-p/i)*inv[p%i]%p;
}
线性筛逆元
#include<iostream>
#include<cstring>
typedef long long ll;
const ll MOD=;
using namespace std;
struct Mat{ll m[][];}a,e;
ll n,p;
Mat Mul(Mat x,Mat y)
{
Mat c;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
c.m[i][j]=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
for(int k=;k<=n;k++)
c.m[i][j]=c.m[i][j]%MOD+x.m[i][k]*y.m[k][j]%MOD;
return c;
}
Mat qpow(Mat x,ll b)
{
Mat ans=e;
while (b)
{
if (b&) ans=Mul(ans,x);
x=Mul(x,x);
b>>=;
}
return ans;
} int main()
{
cin>>n>>p;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
cin>>a.m[i][j];
for(int i=;i<=n;i++)
e.m[i][i]=;
Mat ans=qpow(a,p);
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
cout<<ans.m[i][j]%MOD<<' ';
cout<<'\n';
}
return ;
}
矩阵快速幂
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,he,ta,T;
int f[],q[],num[];
int main()
{
int w,v,s;
scanf("%d%d",&m,&n);
for (int i=;i<=n;i++)
{
scanf("%d%d%d",&w,&v,&s);
if (s>m/w) s=m/w;
for (int d=;d<w;d++)
{
he=ta=;
for (int j=;j<=(m-d)/w;j++)
{
int tmp=f[j*w+d]-v*j;
while (he<ta&&q[ta-]<=tmp) --ta;
q[ta]=tmp,num[ta++]=j;
while (he<ta&&j-num[he]>s) ++he;
f[j*w+d]=max(f[j*w+d],q[he]+v*j);
}
}
}
printf("%d",f[m]);
return ;
}
单调队列优化多重背包
//以"滑动窗口"为例
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e6+;
int n,k,a[N],q[N];
int main()
{
scanf("%d%d",&n,&k);
for (int i=;i<=n;++i) scanf("%d",&a[i]);
int front=,rear=;
for (int i=;i<=n;++i)
{
while (front<=rear&&q[front]+k<=i) ++front;
while (front<=rear&&a[i]<a[q[rear]]) --rear;
q[++rear]=i;
if (i>=k) printf("%d ",a[q[front]]);
}
putchar('\n');
memset(q,,sizeof(q)); //q多次利用
front=,rear=;
for (int i=; i<=n;++i)
{
while (front<=rear&&q[front]+k<=i) ++front;
while (front<=rear&&a[i]>a[q[rear]]) --rear;
q[++rear]=i;
if (i>=k) printf("%d ",a[q[front]]);
}
return ;
}
单调队列
//洛谷P1247
#include<cstdio>
int n,a[];
int main()
{
scanf("%d",&n);
int check=;
for (int i=;i<=n;i++){scanf("%d",&a[i]);check^=a[i];}
if (!check){printf("lose");return ;}
for (int i=;i<=n;i++)
{
if ((check^a[i])<a[i])
{
printf("%d %d\n",a[i]-(check^a[i]),i);
for (int j=;j<=n;j++)
(j!=i)?printf("%d ",a[j]):printf("%d ",check^a[i]);
break;
}
}
return ;
}
Nim游戏输出步骤
OI常用模板的更多相关文章
- (长期更新)OI常用模板
代码很简单的模板就不收录了. DFT 离散傅立叶变换 void dft(pdd *a,int l,bool r){ int i,j=l/2,k; for(i=1;i<l;++i){ if(i&l ...
- 【模板】OI常用模板(待补充)
//PS:最近修改日期:2017-11-07 20:41:44 首先感觉这种模板类的东西写了还是很有意义的,毕竟时不时的可以拿出来借鉴一下. 现在因为刚开始写这一类的东西,所以说还不是很详细,若有读者 ...
- OI 常用模板 手写
线性筛素数 (例题 洛谷P3383) bool p[50000010]; int cnt = 0; int prime[10000010]; inline void init() { int N = ...
- NDK(10)Android.mk各属性简介,Android.mk 常用模板
参考 : http://blog.csdn.net/hudashi/article/details/7059006 本文内容: Android.mk简介, 各属性表, 常用Android.mk模板 1 ...
- IDEA学习——模板及其常用模板
模板及其常用模板 (1)psvm (2)sout sout / soutp / soutv / 变量.sout (3)fori iter增强for循环 itar普通for循环 (4)list.for ...
- Vue常用模板语法
常用模板语法 本篇将在上一篇的基础上记录文本渲染.表达式.过滤器以及常用指令的简单用法. 一.文本渲染 Vue支持动态渲染文本,即在修改属性的同时,实时渲染文本内容.同时为了提高渲染效率,也支持只 ...
- html5常用模板下载网站
html5常用模板下载网站 开创者素材.站长素材.模板之家 推荐葡萄家园素材网,他们网页模板栏目有个HTML模板,很多静态源码.应该是你所需要的. html静态页面模板 还是服饰素材啊 朋友 设计云 ...
- NDK(10)Android.mk各属性简介,Android.mk 常用模板--未完
参考 : http://blog.csdn.net/hudashi/article/details/7059006 1. Android.mk简介 Android.mk文件是GNU Makefile的 ...
- WordPress主题模板层次和常用模板函数
首页: home.php index.php 文章页: single-{post_type}.php – 如果文章类型是videos(即视频),WordPress就会去查找single-videos. ...
随机推荐
- 一 Hibernate入门
Hibernate环境搭建 Hibernate的API Hibernate的CRUD EE三层结构: web层 业务逻辑层 持久层 jdbc,DBUTils,Hibernate Hib ...
- AC自动机 (模板)
AC自动机是用来干什么的: AC自动机是用来解决多模匹配问题,例如有单词s1,s2,s3,s4,s5,s6,问:在文本串ss中有几个单词出现过,类似. AC自动机实现这个功能需要三个部分: 1.将所有 ...
- 虚拟机上安装SVN服务
服务器端安装SVN(centos)1.yum install subversion2.svn的相关配置1创建一个SVN仓库(所有项目存放与管理)mkdir -p /svndata/projects2. ...
- 使用JS写一个计算器
先上效果图: 简单的加减乘除功能还是有的,所以我们就考虑怎么来实现这个功能. 根据预期效果,可以确定页面中的布局要用到table tr td. 所以先放上页面布局,table的边框宽度border,c ...
- android中的简单animation(四)3D transition
animation_main_screen.xml: <?xml version="1.0" encoding="utf-8"?> <Fram ...
- HDU3306-Another kind of Fibonacci(矩阵构造)
Another kind of Fibonacci Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- Day6 - J - Cartesian Tree POJ - 2201
Let us consider a special type of a binary search tree, called a cartesian tree. Recall that a binar ...
- 7个现在就该学习Python 的理由【80%的人都不知道】
Python 是一门更注重可读性和效率的语言,尤其是相较于 Java,PHP 以及 C++ 这样的语言,它的这两个优势让其在开发者中大受欢迎. 诚然,它有点老了,但仍是 80 后啊 —— 至少没有 C ...
- python反序列化漏洞
原理在网页源码中如果出现将用户输入数据进行反序列化当成参数输出时,出现漏洞,可造成任意命令执行例如网页源码try: become = self.get_argument('become') ...
- poj 1027 Ignatius and the Princess II全排列
Ignatius and the Princess II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ( ...