线性基
template<typename T,int maxn>struct basis{
T a[maxn];
basis(){
memset(a,0,sizeof(a));
}
bool insert(T k){
for(int i=maxn-1;i>=0;i--){
if(k>>i&1){
if(!a[i])return a[i]=k,1;
k^=a[i];
}
}
return 0;
}
T query1(T ans=0){
for(int i=maxn-1;i>=0;i--)ans=max(ans,ans^a[i]);
return ans;
}
};
矩阵
template<typename T,int maxn1,int maxn2>struct matrix{
T v[maxn1][maxn2];
template<int maxn3>matrix<T,maxn1,maxn3>operator*(matrix<T,maxn3,maxn2>a){
matrix<T,maxn1,maxn3>ans;
memset(ans.v,0,sizeof(ans.v));
for(int i=0;i<maxn1;i++)for(int k=0;k<maxn3;k++)for(int j=0;j<maxn2;j++)ans.v[i][j]=(ans.v[i][j]+v[i][k]*a.v[k][j])%mod;
return ans;
}
};
template<typename T,int maxn>matrix<T,maxn,maxn>qpow(matrix<T,maxn,maxn>a,T b){
matrix<T,maxn,maxn>ans;
memset(ans.v,0,sizeof(ans.v));
for(int i=0;i<maxn;i++)ans.v[i][i]=1;
for(;b;b>>=1)
{
if(b&1)ans=ans*a;
a=a*a;
}
return ans;
}
Miller-Rabin
long long qmul(long long a,long long b,long long n){
return ((unsigned long long)a*b-(unsigned long long)((long double)a/n*b)*n+n)%n;
}
long long qpow(long long a,long long b,long long n,long long ans=1){
for(a%=n;b;b>>=1)b&1&&(ans=qmul(ans,a,n)),a=qmul(a,a,n);
return ans;
}
const long long A[7]={2,325,9375,28178,450775,9780504,1795265022};
bool isprime(long long n){
if(n<=2||~n&1)return n==2;
int t=__builtin_ctzll(n-1);
long long u=(n-1)>>t,a,v;
for(int i=0,s;i<7;i++){
a=A[i],v=qpow(a,u,n);
if(a%n==0||v==1)continue;
for(s=0;s<t;s++,v=qmul(v,v,n))if(v==n-1)break;
if(s==t)return 0;
}
return 1;
}
Pollard-Rho
long long qmul(long long a,long long b,long long n){
return ((unsigned long long)a*b-(unsigned long long)((long double)a/n*b)*n+n)%n;
}
long long F(long long x,long long c,long long n){
return (qmul(x,x,n)+c)%n;
}
long long pollard_rho(long long n){
long long c=rand()%(n-1)+1,s=0,t=0,v=1;
for(int g=1;;g<<=1,s=t){
for(int i=1;i<=g;i++){
t=F(t,c,n),v=qmul(v,abs(t-s),n);
if(!v)return n;
if(i%127==0){
long long d=gcd(v,n);
if(d>1)return d;
}
}
long long d=gcd(v,n);
if(d>1)return d;
}
}
Lucas
template<typename T>T __C(T n,T m,T p,T f[]){
return m>n?0:f[n]*qpow(f[m],p-2,p)%p*qpow(f[n-m],p-2,p)%p;
}
template<typename T>T C(T n,T m,T p,T f[]){
return m?__C(n%p,m%p,p,f)*C(n/p,m/p,p,f)%p:1;
}
template<typename T>void init(T f[],T p){
f[0]=1;
for(T i=1;i<=p;i++)f[i]=f[i-1]*i%p;
}
exLucas
template<typename T>T f(T n,T q,T qk,T r=1){
if(!n)return 1;
for(T i=1;i<=qk;i++)if(i%q)r=r*(i%qk)%qk;
r=qpow(r,n/qk,qk);
for(T i=n/qk*qk+1;i<=n;i++)if(i%q)r=r*(i%qk)%qk;
return r*f(n/q,q,qk)%qk;
}
template<typename T>T getb(T n,T m,T q,T qk,T cnt=0){
for(T i=n;i;i/=q)cnt+=i/q;
for(T i=m;i;i/=q)cnt-=i/q;
for(T i=n-m;i;i/=q)cnt-=i/q;
return qpow(q,cnt,qk)*f(n,q,qk)%qk*inv(f(m,q,qk),qk)%qk*inv(f(n-m,q,qk),qk)%qk;
}
template<typename T>T C(T n,T m,T p,T ans=0){
vector<T>a,b,c;
T temp=p;
for(T i=2;i*i<=p;i++){
if(p%i==0){
T t=1;
while(p%i==0)p/=i,t*=i;
a.push_back(t),c.push_back(i);
}
}
if(p>1)a.push_back(p),c.push_back(p);
for(int i=0;i<a.size();i++)b.push_back(getb(n,m,c[i],a[i]));
for(int i=0;i<a.size();i++)ans=(ans+b[i]*(temp/a[i])%temp*inv(temp/a[i],a[i])%temp)%temp;
return ans;
}
CRT
template<typename T>T crt(int n,T a[],T b[]){
T m=1,ans=0;
for(int i=1;i<=n;i++)m*=a[i];
for(int i=1;i<=n;i++)ans=(ans+b[i]*(m/a[i])%m*inv(m/a[i],a[i])%m)%m;
return ans;
}
exCRT
template<typename T>T excrt(int n,T a[],T b[]){
T a1=a[1],b1=b[1];
for(int i=2;i<=n;i++){
T c=b[i]-b1,x,y,d=gcd(a1,a[i]);
exgcd(a1,a[i],x,y);
if(c%d==0)x=(x%(a[i]/d)*(c/d)%(a[i]/d)+a[i]/d)%(a[i]/d),b1+=x*a1,a1*=a[i]/d;
else return -1;
}
return b1;
}
高精度
const int BIT=8,MOD=1e8,maxlen=1e4+5;
struct bign{
vector<int>a;
bool f;
bign(){
a.clear(),f=0;
}
bign(const char s[]){
int i=0,l=strlen(s),j;
if(a.clear(),f=0,s[0]=='-')i=f=1;
if(s[i]=='0')return;
j=(l-i-1)%BIT+1,a.push_back(0);
for(;i<l;(a.back()*=10)+=s[i++]-'0',j--)if(!j)a.push_back(0),j=BIT;
reverse(a.begin(),a.end());
}
bign(const string &s){
*this=s.c_str();
}
bign(int x){
a.clear(),x<0?(x=-x,f=1):(f=0);
if(x)x<MOD?(a.push_back(x)):(a.push_back(x%MOD),a.push_back(x/MOD));
}
bign(long long x){
a.clear(),x<0?(x=-x,f=1):(f=0);
while(x>MOD)a.push_back(x%MOD),x/=MOD;
a.push_back(x);
}
friend istream& operator>>(istream &in,bign &x){
char c[maxlen];
return cin>>c,x=c,in;
}
friend ostream& operator<<(ostream& out,const bign &x){
int i=x.a.size();
if(!i)return putchar('0'),out;
if(x.f)putchar('-');
char sw[BIT+1];
for(cout<<x.a[--i];i--;){
for(int j=0;j<BIT;j++)sw[j]='0';
sw[BIT]='\0';
int l=BIT,al=x.a[i];
while(al)sw[--l]=al%10+'0',al/=10;
cout<<sw;
}
return out;
}
explicit operator int(){
int l=a.size(),i,r=0;
for(i=l-1;i>=0;i--)r=r*MOD+a[i];
return f?-r:r;
}
explicit operator long long(){
int l=a.size(),i;
long long r=0;
for(i=l-1;i>=0;i--)r=r*MOD+a[i];
return f?-r:r;
}
explicit operator bool()const{
return !a.empty();
}
int abscmp(const bign &x)const{
int l=a.size(),o=x.a.size();
if(l!=o)return l<o?-1:1;
while(l--)if(a[l]!=x.a[l])return a[l]<x.a[l]?-1:1;
return 0;
}
int cmp(const bign &x)const{
if(a.empty())return x.a.empty()?0:(x.f?1:-1);
if(x.a.empty())return f?-1:1;
if(!f&&x.f)return 1;
if(f&&!x.f)return -1;
return f?-abscmp(x):abscmp(x);
}
friend bool operator<(const bign &x,const bign &y){
return x.cmp(y)<0;
}
friend bool operator>(const bign &x,const bign &y){
return x.cmp(y)>0;
}
friend bool operator<=(const bign &x,const bign &y){
return x.cmp(y)<=0;
}
friend bool operator>=(const bign &x,const bign &y){
return x.cmp(y)>=0;
}
friend bool operator==(const bign &x,const bign&y){
return x.cmp(y)==0;
}
friend bool operator!=(const bign &x,const bign &y){
return x.cmp(y)!=0;
}
bign& operator+(){
return *this;
}
bign operator-(){
bign x=*this;
return x.f^=1,x;
}
void add1(){
if(++a[0]==MOD){
a.push_back(0);
for(int i=0;a[i]==MOD;i++)a[i]=0,a[i+1]++;
if(!a.back())a.pop_back();
}
}
void sub1(){
if(--a[0]==-1){
for(int i=0;a[i]==-1;i++)a[i]+=MOD,a[i+1]--;
if(!a.back())a.pop_back();
}
}
bign& operator++(){
return a.empty()?(a.push_back(1),f=0,void()):(f?sub1():add1()),*this;
}
bign& operator--(){
return a.empty()?(a.push_back(1),f=1,void()):(f?add1():sub1()),*this;
}
bign operator++(int){
bign x=*this;
return a.empty()?(a.push_back(1),f=0,void()):(f?sub1():add1()),x;
}
bign operator--(int){
bign x=*this;
return a.empty()?(a.push_back(1),f=1,void()):(f?add1():sub1()),x;
}
void fit(){
while(!a.empty()&&!a.back())a.pop_back();
}
void add(const bign &x){
int i,l=a.size(),o=x.a.size(),j;
if(l<o)a.resize(o);
a.push_back(0);
for(i=0;i<o;i++){
j=a[i]+x.a[i];
if(j>=MOD)j-=MOD,a[i+1]++;
a[i]=j;
}
fit();
}
void sub(const bign &x){
int i,l=a.size(),o=x.a.size(),j;
for (i=0;i<o;++i){
j=a[i]-x.a[i];
if(j<0)j+=MOD,--a[i+1];
a[i]=j;
}
for(i=o;i<l;i++)if(a[i]<0)a[i]+=MOD,a[i+1]--;
fit();
}
void mul(const bign &x){
int i,j,l=a.size(),o=x.a.size(),k=l+o;
vector<long long>C(k+2,0);
for(i=0;i<o;i++)for(j=0;j<l;j++)C[i+j]+=x.a[i]*1ll*a[j];
for(i=0,a.resize(k);i<k;++i)C[i+1]+=C[i]/MOD,a[i]=C[i]%MOD;
fit();
}
int div(const int &x){
int i,l=a.size();
long long w=0;
for(i=l-1;i>=0;i--)w=w*MOD+a[i],a[i]=w/x,w-=(long long)(a[i])*x;
return fit(),w;
}
bign div(const bign &x){
int i,l=a.size(),o=x.a.size(),j=l-o;
long long u,v,w;
bign r,k=x;
k.f=0;
if(j<0)return r=*this,*this=0,r;
for(i=l-1;i>j;i--)r=r*MOD+a[i];
for(i=j,a.resize(j+1);i>=0;i--){
r=r*MOD+a[i],u=0,v=MOD;
while(v-u>1){
w=(u+v)>>1;
if(k*w<=r)u=w;
else v=w;
}
a[i]=u,r-=k*a[i];
}
return fit(),r;
}
bign& operator+=(const bign &x){
if(f==x.f)add(x);
else if(abscmp(x)>=0)sub(x);
else{
bign y=x;
y.sub(*this),*this=y;
}
return *this;
}
bign& operator-=(const bign &x){
if(f!=x.f)add(x);
else if(abscmp(x)>=0)sub(x);
else{
bign y=x;
y.sub(*this),*this=y,f=!f;
}
return *this;
}
bign& operator*=(const bign &x){
return mul(x),f=(f!=x.f),*this;
}
bign& operator/=(const int &x){
return div(abs(x)),f=!((f&&x<0)||(!f&&x>0)),*this;
}
bign& operator/=(const bign &x){
return div(x),f=(f!=x.f),*this;
}
bign& operator/=(const long long &x){
return *this/=(bign)x;
}
bign& operator%=(const int &x){
return *this=f?-div(abs(x)):div(abs(x));
}
bign& operator%=(const bign &x){
return *this=(f?-div(x):div(x));
}
bign& operator%=(const long long &x){
return *this%=(bign)x;
}
friend bign operator+(bign x,const bign &y){
return x+=y,x;
}
friend bign operator-(bign x,const bign &y){
return x-=y,x;
}
friend bign operator*(bign x,const bign &y){
return x*=y,x;
}
friend bign operator/(bign x,const long long &y){
return x/=y,x;
}
friend bign operator/(bign x,const int &y){
return x/=y,x;
}
friend bign operator/(bign x,const bign &y){
return x/=y,x;
}
friend bign operator%(bign x,const long long &y){
return x%=y,x;
}
friend bign operator%(bign x,const int &y){
return x%=y,x;
}
friend bign operator%(bign x,const bign &y){
return x%=y,x;
}
};
void swap(bign &x,bign &y){
swap(x.f,y.f),swap(x.a,y.a);
}
bign abs(bign x){
return x.f=0,x;
}
bign pow(bign a,int b){
bign r=1;
for(;b;b>>=1){
if(b&1)r*=a;
a*=a;
}
return r;
}
bign gcd(bign a,bign b){
bign r=1;
while(1){
if(!a||!b)return (a+b)*r;
while(a.a[0]>>1&&b.a[0]>>1==0)r*=2,a/=2,b/=2;
while(a.a[0]>>1==0)a/=2;
while(b.a[0]>>1==0)b/=2;
if(a<b)swap(a,b);
a-=b;
}
}
逆元(费马小定理)
template<typename T>T qpow(T a,T b,T n,T ans=1){
for(a%=n;b;b>>=1)b&1&&(ans=1ll*ans*a%n),a=1ll*a*a%n;
return ans;
}
template<typename T>T inv(T a,T b)
{
return qpow(a,b-2,b);
}
逆元(扩展欧几里得)
template<typename T>void exgcd(T a,T b,T &x,T &y){
b?(exgcd(b,a%b,y,x),y-=a/b*x):(x=1,y=0);
}
template<typename T>T inv(T a,T b){
T x,y;
return exgcd(a,b,x,y),(x%b+b)%b;
}
线性求前 n 个数的逆元
template<typename T>void inv1(int n,T p,T inv[]){
inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=(p-p/i)*inv[p%i]%p;
}
离线逆元
template<typename T>void inv_fac(int n,T p,T a[],T ans[]){
T fac[n+5],vac;
fac[0]=1;
for(int i=1;i<=n;i++)fac[i]=fac[i-1]*a[i]%p;
vac=inv(fac[n],p),ans[n]=fac[n-1]*vac%p;
for(int i=n-1;i>=1;i--)vac=vac*a[i+1]%p,ans[i]=fac[i-1]*vac%p;
}
阶乘逆元
template<typename T>void inv_fac(int n,T p,T fac[],T vac[]){
fac[0]=1;
for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%p;
vac[0]=1,vac[n]=inv(fac[n],p);
for(int i=n-1;i>=1;i--)vac[i]=vac[i+1]*(i+1)%p;
}
快速幂
template<typename T>T qpow(T a,T b,T n,T ans=1){
for(a%=n;b;b>>=1)b&1&&(ans=1ll*ans*a%n),a=1ll*a*a%n;
return ans;
}
快速乘
long long qmul(long long a,long long b,long long n){
return ((unsigned long long)a*b-(unsigned long long)((long double)a/n*b)*n+n)%n;
}
gcd与lcm
template<typename T>T gcd(T m,T n){
return n?gcd(n,m%n):m;
}
template<typename T>T lcm(T m,T n){
return n/gcd(n,m)*m;
}
BSGS
template<typename T>T bsgs(T a,T b,T n){
unordered_map<T,T>p;
T m=sqrt(n)+1;
a%=n,b%=n;
if(b==1)return 0;
for(T i=0,t=b;i<m;i++,t=t*a%n)p[t]=i;
for(T i=1,t=a;i<m;i++)a=a*t%n;
for(T i=1,t=a;i<=m;i++,t=t*a%n)if(p.count(t))return m*i-p[t];
return -1;
}
exBSGS
template<typename T>T gcd(T m,T n){
return n?gcd(n,m%n):m;
}
template<typename T>void exgcd(T a,T b,T &x,T &y){
b?(exgcd(b,a%b,y,x),y-=a/b*x):(x=1,y=0);
}
template<typename T>T inv(T a,T b){
T x,y;
exgcd(a,b,x,y);
return (x%b+b)%b;
}
template<typename T>T bsgs(T a,T b,T n){
unordered_map<T,T>p;
T m=sqrt(n)+1;
a%=n,b%=n;
if(b==1)return 0;
for(T i=0,t=b;i<m;i++,t=t*a%n)p[t]=i;
for(T i=1,t=a;i<m;i++)a=a*t%n;
for(T i=1,t=a;i<=m;i++,t=t*a%n)if(p.count(t))return m*i-p[t];
return -1;
}
template<typename T>T exbsgs(T a,T b,T n){
b%=n;
if(b==1||n==1)return 0;
T k=0,t=1;
for(T d=gcd(a,n);d!=1;d=gcd(a,n)){
if(b%d)return -1;
k++,b/=d,n/=d,t=t*(a/d)%n;
if(t==b)return k;
}
T ans=bsgs(a,b*inv(t,n)%n,n);
return ans==-1?-1:ans+k;
}
质数筛
int prime_init(int n,int prime[],bool a[],int cnt=0){
for(int i=2;i<=n;i++)a[i]=1;
for(int i=2;i<=n;i++){
if(a[i])prime[++cnt]=i;
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
a[i*prime[j]]=0;
if(i%prime[j]==0)break;
}
}
return cnt;
}
欧拉函数线性筛
int phi_init(int n,int prime[],int phi[],bool a[],int cnt=0){
phi[1]=1;
for(int i=2;i<=n;i++)a[i]=1;
for(int i=2;i<=n;i++){
if(a[i])prime[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
a[i*prime[j]]=0;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
return cnt;
}
莫比乌斯函数线性筛
int mu_init(int n,int prime[],int mu[],bool a[],int cnt=0){
mu[1]=1;
for(int i=2;i<=n;i++)a[i]=1;
for(int i=2;i<=n;i++){
if(a[i])prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
a[i*prime[j]]=0;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
return cnt;
}
约数个数线性筛
int d_init(int n,int prime[],int d[],bool a[],int cnt=0){
d[1]=1;
for(int i=2;i<=n;i++)a[i]=1;
for(int i=2;i<=n;i++){
if(a[i])prime[++cnt]=i,num[i]=1,d[i]=2;
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
a[i*prime[j]]=0;
if(i%prime[j]==0){
num[i*prime[j]]=num[i]+1,d[i*prime[j]]=d[i]/(num[i]+1)*(num[i*prime[j]]+1);
break;
}
else num[i*prime[j]]=1,d[i*prime[j]]=d[i]*d[prime[j]];
}
}
return cnt;
}
杜教筛
long long getsum1(int x){
if(x<=bn)return phi[x];
if(sum1.count(x))return sum1[x];
long long ans=1ll*x*(x+1)/2;
for(int l=2,r;l<=x;l=r+1)r=x/(x/l),ans-=(r-l+1)*getsum1(x/l);
return sum1[x]=ans;
}
long long getsum2(int x){
if(x<=bn)return mu[x];
if(sum2.count(x))return sum2[x];
long long ans=1;
for(int l=2,r;l<=x;l=r+1)r=x/(x/l),ans-=(r-l+1)*getsum2(x/l);
return sum2[x]=ans;
}
随机数生成器
mt19937 engine(chrono::steady_clock::now().time_since_epoch().count());
template<typename T>T randint(T l,T r){
return uniform_int_distribution<T>(l,r)(engine);
}
template<typename T>T random(T l,T r){
return uniform_real_distribution<T>(l,r)(engine);
}
计时器
chrono::steady_clock::time_point s=chrono::steady_clock::now();
double get_time(){
return chrono::duration<double,milli>(chrono::steady_clock::now()-s).count();
}