【算法竞赛】好用的模版/注意要点
【算法竞赛】一些好用的模版/注意要点
火车头(2026.07.06更新)
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define whiteink signed main
#define fi first
#define sc second
#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl
#define Yes cout<<"Yes"<<endl
#define No cout<<"No"<<endl
#define yes cout<<"yes"<<endl
#define no cout<<"no"<<endl
#define pb push_back
#define pq priority_queue
#define all(x) x.begin(),x.end()
using i64=long long;
using i128=__int128;
using u64=unsigned long long;
using u128 = unsigned __int128;
typedef pair<int,int> PII;
typedef pair<i64,i64> P64;
typedef long double ld;
typedef pair<long double,long double> Pld;
mt19937_64 rng;
//std::random_device rd;
//unsigned int seed = rd();
//rng.seed(seed);
//rng();
template<typename T>
T whink_max(T a,T b){return a>b?a:b;}
template<typename T>
T whink_min(T a,T b){return a<b?a:b;}
template<typename T>
bool cmp(T a,T b){return a>b;}
const int inf_int=0x3f3f3f3f;
const i64 inf_i64=0x3f3f3f3f3f3f3f3f;
const i64 mod=998244353LL;
int dx[8]={1,0,-1,0,1,1,-1,-1},dy[8]={0,1,0,-1,1,-1,1,-1};
//快读快写
inline char nc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template <typename T> void read(T &x){
x=0;
T f=1;
char ch=nc();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=nc();
}
while(ch>='0' && ch<='9'){
x=x*10+ch-'0';
ch=nc();
}
x*=f;
}
template <typename T> void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
}
//快速幂
i64 qmi(i64 a,i64 k,i64 p){
a%=p;
i64 res=1LL;
while(k){
if(k&1LL) res=res*a%p;
k>>=1LL;//删去k的末位
a=a*a%p;
}
return res;
}
//gcd
i64 gcd(i64 a,i64 b){
return b?gcd(b,a%b):a;
}
//求约数
vector<i64> get_divisors(i64 qaq){
vector<i64> res;
for(i64 i=1;i<=qaq/i;i++){
if(qaq%i==0){
res.push_back(i);
if(i!=qaq/i) res.push_back(qaq/i);
}
}
sort(res.begin(),res.end());
return res;
}
//线性筛求质数序列
const int PRIMES_MAXN=1e6+10;
int primes_cnt=0;
vector<i64> primes;
vector<bool> primes_st;
void get_primes(int qaq){
primes.resize(PRIMES_MAXN,0);
primes_st.resize(PRIMES_MAXN,0);
for(int i=2;i<=qaq;i++){
if(!primes_st[i]) primes[primes_cnt++]=i;
for(int j=0;primes[j]<=qaq/i;j++){
primes_st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
//组合数;使用时记得反过来!
const int FACT_MAX=1e6+10;
vector<i64> fact; // 存储阶乘
vector<i64> inv_fact; // 存储阶乘的逆元
void precompute(){
fact.resize(FACT_MAX,0);
inv_fact.resize(FACT_MAX,0);
fact[0]=1;
for(int i=1;i<FACT_MAX;i++) {
fact[i]=fact[i-1]*i%mod;
}
inv_fact[FACT_MAX-1]=qmi(fact[FACT_MAX-1],mod-2LL,mod);
for(int i=FACT_MAX-2;i>=0;i--){
inv_fact[i]=inv_fact[i+1]*(i+1)%mod;
}
}
i64 C(i64 n,i64 k) {
if(n<0 || k<0 || n<k) return 0;
return fact[n]*inv_fact[k]%mod*inv_fact[n-k]%mod;
}
i64 A(i64 n,i64 k) {
if(n<0 || k<0 || n<k) return 0;
return fact[n]*inv_fact[n-k]%mod;
}
const int N=3e5+10;
int n;
void solve(){
}
whiteink(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
//precompute();
//get_primes(1e6);
int T=1;
cin>>T;
while(T--) solve();
return 0;
}
注:换成vector+resize是因为会卡常(悲

取模运算类
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define whiteink signed main
#define fi first
#define sc second
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
using i128 = __int128;
template<class T>
constexpr T power(T a, u64 b, T res = 1) {
for (; b != 0; b /= 2, a *= a) {
if (b & 1) {
res *= a;
}
}
return res;
}
template<u32 P>
constexpr u32 mulMod(u32 a, u32 b) {
return u64(a) * b % P;
}
template<u64 P>
constexpr u64 mulMod(u64 a, u64 b) {
u64 res = a * b - u64(1.L * a * b / P - 0.5L) * P;
res %= P;
return res;
}
constexpr i64 safeMod(i64 x, i64 m) {
x %= m;
if (x < 0) {
x += m;
}
return x;
}
constexpr std::pair<i64, i64> invGcd(i64 a, i64 b) {
a = safeMod(a, b);
if (a == 0) {
return {b, 0};
}
i64 s = b, t = a;
i64 m0 = 0, m1 = 1;
while (t) {
i64 u = s / t;
s -= t * u;
m0 -= m1 * u;
std::swap(s, t);
std::swap(m0, m1);
}
if (m0 < 0) {
m0 += b / s;
}
return {s, m0};
}
template<std::unsigned_integral U, U P>
struct ModIntBase {
public:
constexpr ModIntBase() : x(0) {}
template<std::unsigned_integral T>
constexpr ModIntBase(T x_) : x(x_ % mod()) {}
template<std::signed_integral T>
constexpr ModIntBase(T x_) {
using S = std::make_signed_t<U>;
S v = x_ % S(mod());
if (v < 0) {
v += mod();
}
x = v;
}
constexpr static U mod() {
return P;
}
constexpr U val() const {
return x;
}
constexpr ModIntBase operator-() const {
ModIntBase res;
res.x = (x == 0 ? 0 : mod() - x);
return res;
}
constexpr ModIntBase inv() const {
auto v = invGcd(x, mod());
assert(v.first == 1);
return v.second;
}
constexpr ModIntBase &operator*=(const ModIntBase &rhs) & {
x = mulMod<mod()>(x, rhs.val());
return *this;
}
constexpr ModIntBase &operator+=(const ModIntBase &rhs) & {
x += rhs.val();
if (x >= mod()) {
x -= mod();
}
return *this;
}
constexpr ModIntBase &operator-=(const ModIntBase &rhs) & {
x -= rhs.val();
if (x >= mod()) {
x += mod();
}
return *this;
}
constexpr ModIntBase &operator/=(const ModIntBase &rhs) & {
return *this *= rhs.inv();
}
friend constexpr ModIntBase operator*(ModIntBase lhs, const ModIntBase &rhs) {
lhs *= rhs;
return lhs;
}
friend constexpr ModIntBase operator+(ModIntBase lhs, const ModIntBase &rhs) {
lhs += rhs;
return lhs;
}
friend constexpr ModIntBase operator-(ModIntBase lhs, const ModIntBase &rhs) {
lhs -= rhs;
return lhs;
}
friend constexpr ModIntBase operator/(ModIntBase lhs, const ModIntBase &rhs) {
lhs /= rhs;
return lhs;
}
friend constexpr std::istream &operator>>(std::istream &is, ModIntBase &a) {
i64 i;
is >> i;
a = i;
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const ModIntBase &a) {
return os << a.val();
}
friend constexpr bool operator==(const ModIntBase &lhs, const ModIntBase &rhs) {
return lhs.val() == rhs.val();
}
friend constexpr std::strong_ordering operator<=>(const ModIntBase &lhs, const ModIntBase &rhs) {
return lhs.val() <=> rhs.val();
}
private:
U x;
};
template<u32 P>
using ModInt = ModIntBase<u32, P>;
template<u64 P>
using ModInt64 = ModIntBase<u64, P>;
struct Barrett {
public:
Barrett(u32 m_) : m(m_), im((u64)(-1) / m_ + 1) {}
constexpr u32 mod() const {
return m;
}
constexpr u32 mul(u32 a, u32 b) const {
u64 z = a;
z *= b;
u64 x = u64((u128(z) * im) >> 64);
u32 v = u32(z - x * m);
if (m <= v) {
v += m;
}
return v;
}
private:
u32 m;
u64 im;
};
template<u32 Id>
struct DynModInt {
public:
constexpr DynModInt() : x(0) {}
template<std::unsigned_integral T>
constexpr DynModInt(T x_) : x(x_ % mod()) {}
template<std::signed_integral T>
constexpr DynModInt(T x_) {
int v = x_ % int(mod());
if (v < 0) {
v += mod();
}
x = v;
}
constexpr static void setMod(u32 m) {
bt = m;
}
static u32 mod() {
return bt.mod();
}
constexpr u32 val() const {
return x;
}
constexpr DynModInt operator-() const {
DynModInt res;
res.x = (x == 0 ? 0 : mod() - x);
return res;
}
constexpr DynModInt inv() const {
auto v = invGcd(x, mod());
assert(v.first == 1);
return v.second;
}
constexpr DynModInt &operator*=(const DynModInt &rhs) & {
x = bt.mul(x, rhs.val());
return *this;
}
constexpr DynModInt &operator+=(const DynModInt &rhs) & {
x += rhs.val();
if (x >= mod()) {
x -= mod();
}
return *this;
}
constexpr DynModInt &operator-=(const DynModInt &rhs) & {
x -= rhs.val();
if (x >= mod()) {
x += mod();
}
return *this;
}
constexpr DynModInt &operator/=(const DynModInt &rhs) & {
return *this *= rhs.inv();
}
friend constexpr DynModInt operator*(DynModInt lhs, const DynModInt &rhs) {
lhs *= rhs;
return lhs;
}
friend constexpr DynModInt operator+(DynModInt lhs, const DynModInt &rhs) {
lhs += rhs;
return lhs;
}
friend constexpr DynModInt operator-(DynModInt lhs, const DynModInt &rhs) {
lhs -= rhs;
return lhs;
}
friend constexpr DynModInt operator/(DynModInt lhs, const DynModInt &rhs) {
lhs /= rhs;
return lhs;
}
friend constexpr std::istream &operator>>(std::istream &is, DynModInt &a) {
i64 i;
is >> i;
a = i;
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const DynModInt &a) {
return os << a.val();
}
friend constexpr bool operator==(const DynModInt &lhs, const DynModInt &rhs) {
return lhs.val() == rhs.val();
}
friend constexpr std::strong_ordering operator<=>(const DynModInt &lhs, const DynModInt &rhs) {
return lhs.val() <=> rhs.val();
}
private:
u32 x;
static Barrett bt;
};
template<u32 Id>
Barrett DynModInt<Id>::bt = 998244353;
using Z = ModInt<998244353>;
struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}
void init(int m) {
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);
for (int i = n + 1; i <= m; i++) {
_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}
Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;
void solve() {
}
whiteink() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--) solve();
return 0;
}
大根堆和小根堆
//默认大根堆:less<>
priority_queue<int>
priority_queue<long long,vector<long long>,less<long long>>
//小根堆:greater<>
priority_queue<int,vector<int>,greater<int>>
//结构体:重载运算符
//priority_queue 默认会去查找 operator< 来决定元素间的大小关系
/*
【小于号大根堆】
【大于号小根堆】
*/
//大根堆
struct node{
int value;
friend bool operator<(const node &a,const node &b){
return a.value<b.value; //【小于号大根堆】
}
};
priority_queue<node>q;
//小根堆
struct node{
int value;
friend bool operator<(const node &a,const node &b){
return a.value>b.value; //【大于号小根堆】
}
};
priority_queue<node>q;
关闭同步流
->尽量都用cin和cout输入输出->简洁
//注意别和printf和scanf混用
//换行少用endl,多用'\n'
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
//保留n位小数
cout << fixed << setprecision(n) << 变量名 << '\n';
快读快写
//快读快写
inline char nc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template <typename T> void read(T &x){
x=0;
T f=1;
char ch=nc();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=nc();
}
while(ch>='0' && ch<='9'){
x=x*10+ch-'0';
ch=nc();
}
x*=f;
}
template <typename T> void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
}
注意
(1)用nc()读字符串时:要判断nc()!='\0'
(2)注意换行输出用putchar('\n')
高精度逃课大法:__int128
※最大38位
※一定要注意两个下划线!!!
快读里inline int改为__int128
快写里int改为__int128
变量名为__int128
读取整行 + 字符串解析
//先忽略换行符
cin.ignore();
string line;
getline(cin, line);
stringstream ss(line);
int x;
while (ss >> x) {
// 逐个读入
}
读到文件末尾为止
int a, b;
while(cin >> a >> b) {
// 多组测试样例
}
//加EOF
while(scanf("%d%d", &a, &b) != EOF) {
...
}
关于vector
排序+去重
有时候可以不用set,省一个log的复杂度
sort(q.begin(),q.end());
q.erase(unique(q.begin(),q.end()),q.end());
枚举排列
vector<int> p(n);
//p[i]=i;
iota(p.begin(),p.end(),0);
//枚举每个排列 复杂度O(n!*n)->
do{
//p变成了下标数组
for(auto i : p){
a[i] xxxx
}
}
while(next_permutation(p.begin(),p.end()));
set/multiset遍历:迭代器iterator
升序输出
set<int>::iterator it;
for(it=mySet.begin();it!=mySet.end();it++) cout<<*it<<endl;
倒序输出:反向迭代器reverse_iterator``rbegin``rend
set<int>::reverse_iterator it;
for(it=mySet.rbegin();it!=mySet.rend();it++) cout<<*it<<endl;
高精度
高精度加
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> A,B;
string a,b;
vector<int> add(vector<int> &A,vector<int> &B){
vector<int> C;
int t=0;
for(int i=0;i<A.size()||i<B.size();i++){
if(i<A.size()) t+=A[i];
if(i<B.size()) t+=B[i];
C.push_back(t%10) ;
t/=10;
}
if(t) C.push_back(1);
return C;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
vector<int> C=add(A,B);
for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
return 0;
}
高精度减
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool cmp(vector<int> &A,vector<int> &B) {//判断A是否>=B
if(A.size()!=B.size()) return A.size()>B.size();
for(int i=A.size()-1;i>=0;i--){
if(A[i]!=B[i]) return A[i]>B[i];
}
return true;
}
vector<int> sub(vector<int> &A,vector<int> &B){//C=A-B 前提条件A>=B
vector<int> C;
int t=0;
for(int i=0;i<A.size();i++){
t=A[i]-t;
if(i<B.size()) t-=B[i];
C.push_back((t+10)%10);
if(t<0) t=1;
else t=0;
}
//处理前导0
while(C.size()>1 && C.back()==0) C.pop_back();
return C;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
vector<int> A,B;
string a,b;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
if(cmp(A,B)){
vector<int> C=sub(A,B);
for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
}
else{
vector<int> C=sub(B,A);
printf("%c",'-');
for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
}
return 0;
}
高精度乘
高精度除
lambda函数
写check
写sort中的cmp
写大模拟
auto 函数名=[&/空白](引用的变量)->返回的数据类型 { 函数体 };
注意:lambda如果是auto型不能递归->要用function
function<void(int)> dfs=[&](int u)->void{
if(u==n+1){
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
}
for(int i=1;i<=n;i++){
if(!st[i]){
ans[u]=i;
st[i]=1;
dfs(u+1);
st[i]=0;
}
}
};
O3优化(慎用(x
#pragma GCC optimize(3)
#pragma GCC target("avx","f16c","sse3","sse2","sse1")
#pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
#pragma GCC optimize("Ofast","-fgcse","-fgcse-lm","-fipa-sra")
#pragma GCC optimize("-ffast-math","-fpeephole2","-fsched-spec")
#pragma GCC optimize("unroll-loops","-falign-jumps","-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-freorder-functions")
#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("-foptimize-sibling-calls")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("unroll-loops","no-stack-protector")

浙公网安备 33010602011771号