数学

线性基

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();
}
posted @ 2024-03-01 09:35  lgh_2009  阅读(6)  评论(0)    收藏  举报