我的模板
常用
chkmin,chkmax
template<typename T>
bool chkmin(T& x,const T& y){return y<x?(x=y,1):0;}
template<typename T>
bool chkmax(T& x,const T& y){return x<y?(x=y,1):0;}
I/O
getchar 快读
目前看来已经成了时代的眼泪。
template<typename T>
void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch)) f=(ch=='-'?-1:f),ch=getchar();
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
x*=f;
}
template<typename T,typename... Args>
void read(T &x,Args& ...others){
read(x);
read(others...);
}
数学
快速幂
ll power(ll x,ll y,ll mod){
ll r=1;
for(;y;y>>=1,x=x*x%mod){
if(y&1) r=r*x%mod;
}
return r;
}
ll power(ll x,ll y){
ll r=1;
for(;y;y>>=1,x=x*x%Mod){
if(y&1) r=r*x%Mod;
}
return r;
}
扩展欧几里得
void exgcd(ll a,ll b,ll& x,ll& y){
if(!b){
x=1,y=0;
return;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
光速幂
struct FastPower{
const int Size,Base,Mod;
ll *pow1,*pow2;
FastPower(ll base,ll lim,int mod):Size(sqrt(lim)+1),Base(base%mod),Mod(mod),pow1(new ll[Size]),pow2(new ll[Size]){
pow1[0]=pow2[0]=1;
For(i,1,Size-1) pow1[i]=pow1[i-1]*Base%Mod;
ll temp=pow1[Size-1]*Base%Mod;
For(i,1,Size-1) pow2[i]=pow2[i-1]*temp%Mod;
}
ll operator()(ll p){return pow1[p%Size]*pow2[p/Size]%Mod;}
~FastPower(){delete[] pow1;delete[] pow2;}
};
分解质因数
vector<pair<ll,int>> prime_factors(ll x){
vector<pair<ll,int>> res;
auto _add=[&](int i){
if(x%i==0){
res.emplace_back(i,0);
while(x%i==0) ++res.back().second,x/=i;
}
};
_add(2),_add(3);
for(int i=5;1LL*i*i<=x;i+=6) _add(i),_add(i+2);
if(x>1) res.emplace_back(x,1);
return res;
}
多项式
namespace polynomial {
const int N = 5e5 + 5, g = 3;
int lim, lg2[N], rev[N], pwg[N];
inline int getsz(int n) { return 1 << (lg2[n - 1] + 1); }
[[gnu::constructor]] void init() {
for (int i = 2; i < N; ++i) lg2[i] = lg2[i >> 1] + 1;
for (int h = 2; h <= N; h <<= 1) {
int gn = Pow(g, (Mod - 1) / h);
pwg[h >> 1] = 1;
for (int i = (h >> 1) + 1; i < h; ++i) pwg[i] = 1LL * pwg[i - 1] * gn % Mod;
}
}
void getrev(int n) {
if (n == lim) return;
for (int i = 1; i < (lim = n); ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) ? n >> 1 : 0);
}
void ntt(vector<int>& f, int tp) {
int n = f.size();
getrev(n);
for (int i = 0; i < n; ++i)
if (i < rev[i])
swap(f[i], f[rev[i]]);
for (int h = 2; h <= n; h <<= 1)
for (int i = 0, p = h >> 1; i < n; i += h)
for (int j = i; j < i + p; ++j) {
int t = 1LL * f[j + p] * pwg[j - i + p] % Mod;
f[j + p] = (f[j] - t + Mod) % Mod, (f[j] += t) %= Mod;
}
if (tp == -1) {
int inv = Pow(n, Mod - 2);
reverse(f.begin() + 1, f.end());
for (int i = 0; i < n; ++i) f[i] = 1LL * f[i] * inv % Mod;
}
}
struct poly {
vector<int> a;
poly() = default;
poly(int deg): a(deg + 1, 0) {}
poly(const vector<int> &v): a(v) {}
poly(const initializer_list<int> &v): a(v) {}
int size() const { return a.size(); }
void resize(int n) { a.resize(n); }
int& operator[](int i) { return a[i]; }
const int& operator[](int i) const { return a[i]; }
poly operator-() const {
auto b = a;
for (auto& x : b) x = (Mod - x) % Mod;
return poly(b);
}
poly mul_xn(int n) const {
auto b = a;
b.insert(b.begin(), n, 0);
return poly(b);
}
poly mod_xn(int n) const {
if (size() <= n)
return *this;
return poly({ a.begin(), a.begin() + n });
}
poly operator+(const poly& rhs) const { return poly(*this) += rhs; }
poly operator-(const poly& rhs) const { return poly(*this) -= rhs; }
poly operator*(const poly& rhs) const { return poly(*this) *= rhs; }
poly& operator+=(const poly& rhs) {
if (size() < rhs.size())
resize(rhs.size());
for (int i = 0; i < rhs.size(); ++i) (a[i] += rhs[i]) %= Mod;
return *this;
}
poly& operator-=(const poly& rhs) {
if (size() < rhs.size())
resize(rhs.size());
for (int i = 0; i < rhs.size(); ++i) (a[i] -= rhs[i] - Mod) %= Mod;
return *this;
}
poly& operator*=(poly rhs) {
int sz = getsz(size() + rhs.size() - 1);
resize(sz), rhs.resize(sz), ntt(a, 1), ntt(rhs.a, 1);
for (int i = 0; i < sz; ++i) a[i] = 1LL * a[i] * rhs[i] % Mod;
return ntt(a, -1), * this;
}
poly derivation() const {
int n = size();
if (!n)
return poly();
vector<int> ret(n - 1);
for (int i = 1; i < n; ++i) ret[i - 1] = 1LL * a[i] * i % Mod;
return poly(ret);
}
poly integral() const {
int n = size();
if (!n)
return poly();
vector<int> ret(n + 1), inv(n + 1, 1);
for (int i = 2; i <= n; ++i) inv[i] = 1LL * inv[Mod % i] * (Mod - Mod / i) % Mod;
for (int i = 1; i <= n; ++i) ret[i] = 1LL * a[i - 1] * inv[i] % Mod;
return poly(ret);
}
poly inv(int n) const {
assert(a[0] != 0), n = getsz(n);
poly ret({(int)Pow(a[0], Mod - 2)});
for (int k = 2; k <= n; k <<= 1) ret *= (poly({2}) - mod_xn(k) * ret).mod_xn(k);
return ret.mod_xn(n);
}
poly log(int n) const {
assert(a[0] == 1), n = getsz(n);
return (derivation() * inv(n)).integral().mod_xn(n);
}
poly exp(int n) const {
assert(a[0] == 0), n = getsz(n);
poly ret({1});
for (int k = 2; k <= n; k <<= 1) ret = (ret * (poly({1}) + mod_xn(k) - ret.log(k))).mod_xn(k);
return ret.mod_xn(n);
}
};
}
using polynomial::poly;
计算几何
基本定义
const double pi=acos(-1),eps=1e-9;
int dcmp(double x,double y=0){
return abs(x-y)<eps?0:(x<y?-1:1);
}
struct Point{
double x,y;
bool operator<(const Point &p){return dcmp(x,p.x)?x<p.x:y<p.y;}
Point operator+(const Point &p){return {x+p.x,y+p.y};}
Point operator-(const Point &p){return {x-p.x,y-p.y};}
Point operator*(double _k){return {x*_k,y*_k};}
Point operator/(double _k){return {x/_k,y/_k};}
double operator*(const Point &p){return x*p.y-y*p.x;}
double dot(const Point &p){return x*p.x+y*p.y;}
double dist(){return hypot(x,y);}
};
struct Circle{
Point p;
double r;
Point at(double theta){
return {p.x+r*cos(theta),p.y+r*sin(theta)};
}
};
struct Line{Point p,vec;};
其他
Point intersect(const Line &p1,const Line &p2){
double _k=(p2.p-p1.p)*p2.vec/(p1.vec*p2.vec);
return p1.p+p1.vec*_k;
}
Line mid_perp(const Point &p1,const Point &p2){
auto _p=p1-p2;
return {(p1+p2)/2,{_p.y,-_p.x}};
}
Circle circum(const Point &p1,const Point &p2,const Point &p3){
auto _p=intersect(mid_perp(p1,p2),mid_perp(p2,p3));
return {_p,Dist(_p,p1)};
}
图论
最大流
template<typename T>
struct MFGraph{
static constexpr T Inf=numeric_limits<T>::max();
const int n;
struct Edge{
int v;
T w;
};
vector<Edge> e;
vector<vector<int>> g;
vector<int> cur,dis,q;
MFGraph(int _n):n(_n),g(n+1){}
bool bfs(int s,int t){
dis.assign(n+1,0),q.assign(n+2,0);
int head=1,tail=0;
q[++tail]=s,dis[s]=1;
while(head<=tail){
int u=q[head++];
for(int i:g[u]){
int v=e[i].v;
if(e[i].w&&!dis[v]){
dis[v]=dis[u]+1,q[++tail]=v;
if(v==t) return 1;
}
}
}
return 0;
}
T dinic(int u,int t,T flow){
if(u==t) return flow;
T rest=flow;
for(int i=cur[u];i<int(g[u].size())&&rest;++i){
cur[u]=i;
int j=g[u][i],v=e[j].v;
if(e[j].w&&dis[v]==dis[u]+1){
T k=dinic(v,t,min(rest,e[j].w));
if(!k) dis[v]=0;
e[j].w-=k,e[j^1].w+=k,rest-=k;
}
}
return flow-rest;
}
void add_edge(int u,int v,T w){
g[u].push_back(e.size()),e.push_back({v,w});
g[v].push_back(e.size()),e.push_back({u,0});
}
T flow(int s,int t){
T res=0;
while(bfs(s,t)){
cur.assign(n+1,0);
T flow;
while((flow=dinic(s,t,Inf))) res+=flow;
}
return res;
}
};
费用流
template<typename T>
struct MCFGraph{
static constexpr T Inf=numeric_limits<T>::max();
const int n;
struct Edge{int v;T w,c;};
vector<Edge> e;
vector<vector<int>> g;
vector<int> pre;
vector<T> dis,aug;
MCFGraph(int _n):n(_n),g(n+1),pre(n+1),aug(n+1){}
bool spfa(int s,int t){
dis.assign(n+1,Inf);
vector<int> inq(n+1),q;
q.push_back(s);
dis[s]=0,inq[s]=1,aug[s]=Inf,aug[t]=0;
For(j,0,int(q.size())-1){
int u=q[j];inq[u]=0;
for(int i:g[u]){
int v=e[i].v;
if(e[i].w&&dis[v]>dis[u]+e[i].c){
dis[v]=dis[u]+e[i].c,pre[v]=i;
aug[v]=min(e[i].w,aug[u]);
if(!inq[v]) q.push_back(v),inq[v]=1;
}
}
}
return dis[t]<Inf;
}
void add_edge(int u,int v,T w,T c){
g[u].push_back(e.size()),e.push_back({v,w,c});
g[v].push_back(e.size()),e.push_back({u,0,-c});
}
pair<T,T> flow(int s,int t){
T res=0,cost=0;
while(spfa(s,t)){
res+=aug[t];
for(int u=t;u!=s;u=e[pre[u]^1].v){
e[pre[u]].w-=aug[t],e[pre[u]^1].w+=aug[t];
cost+=aug[t]*e[pre[u]].c;
}
}
return {res,cost};
}
};
数据结构
哈希表
template<typename Key,typename Val,typename Hash=hash<Key>>
struct HashTable{
static constexpr int B=3141592,E=1e5;
const Hash h;
bool vis[B+E];
Key key[B+E];
Val val[B+E];
HashTable():h(Hash()),vis(){}
size_t locate(const Key &x){
size_t i;
for(i=h(x)%B;vis[i]&&key[i]!=x;++i);
return i;
}
bool insert(const Key &x,const Val &y){
size_t i=locate(x);
if(vis[i]) return 0;
vis[i]=1,key[i]=x,val[i]=y;
return 1;
}
Val *find(const Key &x){
size_t i=locate(x);
return (vis[i]?val+i:nullptr);
}
};
作者:alan-zhao-2007
出处:https://www.cnblogs.com/alan-zhao-2007/p/my-templates.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
Written by Alan_Zhao
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具