【算法竞赛】好用的模版/注意要点

【算法竞赛】一些好用的模版/注意要点

火车头(2025.10.03更新)

#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

using i64=long long;
using i128=__int128;
typedef pair<int,int> PII;
typedef pair<i64,i64> P64;
typedef long double ld;
typedef pair<long double,long double> Pld;
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<int> get_divisors(int qaq){
	vector<int> res;
	for(int 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=5e7+10;
int primes_cnt=0;
vector<int> 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();

    int T=1;
    cin>>T;
    while(T--) solve();
    return 0;
}

注:换成vector+resize是因为会卡常(悲
image

取模运算类

#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 i128=__int128;
typedef pair<int,int> PII;
typedef pair<i64,i64> P64;
typedef long double ld;
typedef pair<long double,long double> Pld;

i64 max64(i64 a,i64 b){return a>b?a:b;}
i64 min64(i64 a,i64 b){return a<b?a:b;}
bool cmp(int a,int b){return a>b;}
bool cmp64(i64 a,i64 b){return a>b;}

const int inf_int=0x3f3f3f3f;
const i64 inf_i64=0x3f3f3f3f3f3f3f3f;
const i64 mod=1e9+7;

int dx[8]={1,0,-1,0,1,1,-1,-1},dy[8]={0,1,0,-1,1,-1,1,-1};

template<typename T>
constexpr T qmi(T x,i64 p){
    T res=1;
    while(p){
        if(p&1)res*=x;
        x*=x,p>>=1;
    }
    return res;
}

template<typename T,T P>
struct ModInt{
    T x;
    constexpr ModInt():x(){}
    constexpr ModInt(i64 x_val):x(norm(x_val%getMod())){}

    constexpr T val()const{return x;}

    static T Mod;
    constexpr static T getMod(){
        return (P>0)?P:Mod;
    }
    constexpr static void setMod(T Mod_){Mod=Mod_;}

    constexpr T norm(T x)const{
        if(x<0)x+=getMod();
        if(x>=getMod())x-=getMod();
        return x;
    }

    static constexpr int mul(int a,int b,int mod){
        return 1LL*a*b%mod;
    }
    static constexpr i64 mul(i64 a,i64 b,i64 mod){
        i64 res=a*b-(i64)(1.l*a*b/mod)*mod;
        res%=mod;
        if(res<0)res+=mod;
        return res;
    }

    explicit constexpr operator T()const{return x;}
    constexpr ModInt operator-()const{
        return norm(getMod()-x);
    }
    constexpr ModInt inv()const{
        assert(x!=0);
        return qmi(*this,getMod()-2);
    }

    constexpr ModInt& operator+=(ModInt rhs){
        x=norm(x+rhs.x);
        return *this;
    }
    constexpr ModInt& operator-=(ModInt rhs){
        x=norm(x-rhs.x);
        return *this;
    }
    constexpr ModInt& operator*=(ModInt rhs){
        x=mul(x,rhs.x,getMod());
        return *this;
    }
    constexpr ModInt& operator/=(ModInt rhs){
        return *this*=rhs.inv();
    }

    friend constexpr ModInt operator+(ModInt lhs,ModInt rhs){return lhs+=rhs;}
    friend constexpr ModInt operator-(ModInt lhs,ModInt rhs){return lhs-=rhs;}
    friend constexpr ModInt operator*(ModInt lhs,ModInt rhs){return lhs*=rhs;}
    friend constexpr ModInt operator/(ModInt lhs,ModInt rhs){return lhs/=rhs;}

    friend constexpr bool operator==(ModInt lhs,ModInt rhs){return lhs.val()==rhs.val();}
    friend constexpr bool operator!=(ModInt lhs,ModInt rhs){return lhs.val()!=rhs.val();}
    friend constexpr bool operator<(ModInt lhs,ModInt rhs){return lhs.val()<rhs.val();}
    friend constexpr bool operator<=(ModInt lhs,ModInt rhs){return lhs.val()<=rhs.val();}
    friend constexpr bool operator>(ModInt lhs,ModInt rhs){return lhs.val()>rhs.val();}
    friend constexpr bool operator>=(ModInt lhs,ModInt rhs){return lhs.val()>=rhs.val();}

    friend constexpr istream& operator>>(istream& is,ModInt& in){
        i64 v;
        is>>v;
        in=ModInt(v);
        return is;
    }
    friend constexpr ostream& operator<<(ostream& os,const ModInt& out){
        return os<<out.val();
    }
};

template<typename T,T P>
T ModInt<T,P>::Mod=P;

const int N=3e5+10;
using mint=ModInt<i64,1000000000000000009LL>;

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

关于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")
posted @ 2025-01-12 15:56  White_ink  阅读(30)  评论(0)    收藏  举报