整这个玩意单纯只是怕打比赛时要粘板子发现找不到了。
缺省源
先是头文件和一堆宏定义,一般都是带着的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lc p<<1
#define rc p<<1|1
#define lb(x) (x&-x)
#define cl fflush(stdout)
#define ch(i) (i-'a')
#define F(i) (i).first
#define S(i) (i).second
#define X(i) (i>n?i-n:i)
#define kw(x,k) ((x>>k)&1)//二进制第 k 位
#define si(i) ((int)i.size())
#define pb push_back
#define vi vector<int>
#define pi pair<int,int>
#define id(x,y) ((x-1)*m+y)//二维平面转一维编号
#define all(x) (x).begin(),(x).end()
#define me(t,x) memset(t,x,sizeof(t))
#define L(i,j,k) for(int (i)=(j);i<=(k);(i)++)
#define R(i,j,k) for(int (i)=(j);i>=(k);(i)--)
#define FST ios::sync_with_stdio(0);cin.tie(0);//关cin流同步
#define ll(i,j,k,l) for(int (i)=(j);i<=(k);(i)+=(l))
#define rr(i,j,k,l) for(int (i)=(j);i>=(k);(i)-=(l))
#define E(i,u) for(int (i)=fir[(u)];(i);(i)=e[(i)].nt)
再是用来Debug的一堆宏定义。
提交时把 #define DEBUG
注释掉就行了。
就不用挨个调试代码去删了。
在调时也减少了弄混变量数组的情况。
#define DEBUG
namespace LOCAL{
#ifdef DEBUG
#define got cout<<"get here"<<'\n';
#define cut cout<<"-------------------------------------------------------------------\n";
#define dg(x) cout<<#x<<" = "<<x<<"\n";//变量x
#define dgb(x) cout<<"binary "<<#x<<" = "<<bitset<30>(x)<<'\n';//x的二进制
#define dg2(l,r) cout<<"["#l","#r"] = ["<<l<<","<<r<<"]\n";//变量l,r
#define dg3(x,y,z) cout<<"{"#x","#y","#z"} = "<<\
"{"<<x<<","<<y<<","<<z<<"}\n";//变量x,y,z
#define dgvi(v) cout<<#v": size= "<<si(v)<<"\nelement: ";\
for(auto p:v) cout<<p<<" ";cout<<'\n';//vector
#define dgar(x,s) cout<<#x": len= "<<s<<"\nelement: ";\
for(int i=1;i<=s;i++) cout<<x[i]<<" \n"[i==s];//数组x前s位
#define dge(x,n) int s=0;L(i,0,n) s+=si(x[i]);cout<<"There are "<<s<<" edges in "<<#x<<'\n';\
L(u,0,n) for(int v:x[u]) cout<<u<<' '<<v<<'\n';//vector中的边
#else
#define got
#define cut
#define dg(x)
#define dgb(x)
#define dg2(l,r)
#define dg3(x,y,z)
#define dgvi(v)
#define dgar(x,s)
#define dge(x,n)
#endif
}using namespace LOCAL;
之后是一个 modint
类的封装。
改编自 \(\color{Black}{j} \color{Red}{iangly}\) 的某个提交中部分代码。
不是任意模数的,要改变 \(P\) 的值。
就按照普通变量类型定义即可,注意没有取模操作,不然 CE。
相同情况下常数较大。
后面的 math
模块是时间复杂度 \(O(n)\) 的,改编自 \(\color{Gold}{kk19212}\) 的代码。
没有直接只是预处理阶乘数组然后直接除是因为这样时间复杂度 \(O(n \log_2 n)\),且常数较大。
const int P=998244353;
int O(int x){return x<0?(x+=P):x<P?x:(x-=P);}
template<class T>
T ksm(T a,ll b){T s=1;for(;b;b>>=1,a*=a) if(b&1) s*=a;return s;}
struct Z{
int x;Z(int x=0):x(O(x)){}Z(ll x):x(O(x%P)){}
int val()const{return x;}Z operator-()const{return Z(O(P-x));}
Z inv()const{assert(x!=0);return ksm(*this,P-2);}
Z&operator*=(const Z&r){x=(ll)(x)*r.x%P;return*this;}
Z&operator+=(const Z&r){x=O(x+r.x);return*this;}
Z&operator-=(const Z&r){x=O(x-r.x);return*this;}
Z&operator/=(const Z&r){return*this*=r.inv();}
friend Z operator*(const Z&l,const Z&r){Z s=l;s*=r;return s;}
friend Z operator+(const Z&l,const Z&r){Z s=l;s+=r;return s;}
friend Z operator-(const Z&l,const Z&r){Z s=l;s-=r;return s;}
friend Z operator/(const Z&l,const Z&r){Z s=l;s/=r;return s;}
friend istream&operator>>(istream&is,Z&a){ll v;is>>v;a=Z(v);return is;}
friend ostream&operator<<(ostream&os,const Z&a){return os<<a.val();}
};namespace math{
Z jc[1000100],ijc[1000100];
void init(int x){
jc[0]=1;L(i,1,x) jc[i]=jc[i-1]*i;
ijc[x]=jc[x].inv();R(i,x,1) ijc[i-1]=ijc[i]*i;
}Z C(int n,int m){return jc[n]*ijc[n-m]*ijc[m];}
Z A(int n,int m){return jc[n]*ijc[n-m];}
}using namespace math;