省选前的复习 - 板子大合集(持续更新)

我太弱了.jpg

有锅的话我不负责


数学

数论的除法都向下取整

long long 快速乘

il ll mul(ll x,ll y,ll mo){return(x*y-(ll)((long double)x/mo*y)*mo+mo)%mo;}

扩展gcd

\(ax+by\equiv\gcd(a,b)\)的一组特解。

直接上代码

il vd exgcd(ll a,ll b,ll&x,ll&y){
    if(!b)x=1,y=0;
    else exgcd(b,a%b,y,x),y-=x*(a/b);
}

\(ax+by=c\)的特解时,先求\(c=\gcd(a,b)\)时的,然后如果\(c\)\(\gcd(a,b)\)的倍数,那么将\(x,y\)分别乘这个倍数即是特解;否则无解。

中国剩余定理

正好今天考到了扩展lucas要用这个就写一下。

设有\(n\)个方程\(x\equiv a_i(\mod m_i)\),所有\(m\)互质

\(M=\prod m_i\),则\(x\)在膜\(M\)下解唯一,为\(x=\sum_{i=1}^n a_iM_iM_i^{-1}\mod M\)

\(M_i=M/m_i\)\(M_i^{-1}\)是在膜\(m_i\)意义下的逆元

扩展lucas

之前好像在哪里写过一个题的现在找不到了。

正好今天考到了就写一下。(然后写了一个晚自习调自闭)

\(n!\mod P\),分解\(P=\prod_{i=1}^mp_i^{e_i}\)

单独考虑每个\(p^e\),最后用crt合并,现在问题是求\(n!=p^k\cdot q\)(求的q是膜\(p^e\)意义下的,而且不能是\(p\)的倍数),这个\(p\)只记录次数,最后统计

\(n!=1\times 2 \times \cdots \times n\)

先不看\(q\),求出\(k\);设\(f(n)\)表示\(n\)对应的\(k\)

\(n!\)\(p\)的倍数有\(\frac{n}{p}\)个,将这些数全部除\(p\),对应着\(1\)\(\frac{n}{p}\),显然\(f(n)=f(\frac{n}{p})+\frac{n}{p}\),边界是\(f(n)=0(n<p)\)

求出这个之后再求阶乘,现在求的是去掉了所有p的

按照\(p^e\)为一个循环节(因为最后要对这个取膜)

\((1\times \cdots\times p^e)^{\frac{n}{p^e}}\times (1\times \cdots (n\mod p^e))\)

\(p^e\)很小,所以可以预处理这个东西(代码中的P),注意for到p的倍数就不乘。

然后\(p\)的倍数除掉\(p\)之后还有一个\((\frac{n}{p})!\),递归处理。

ll p[10],e[10],pe[10],o;//存所有的质数
std::vector<int>P[6];
il ll getk(ll n,ll p){
    ll ret=0;
    while(n)ret+=n/p,n/=p;
    return ret;
}
il ll getfact(ll n,ll p,ll pe,std::vector<int>&P){
    if(n<=1)return 1;
    ll ret=mul(mul(pow(P[pe],n/pe,pe),P[n%pe],pe),getfact(n/p,p,pe,P),pe);
    return ret;
}
il ll getC(ll n,ll m,ll p,ll pe,std::vector<int>&P){
    ll ret=getfact(n,p,pe,P);
    ret=mul(ret,inv(mul(getfact(m,p,pe,P),getfact(n-m,p,pe,P),pe),pe),pe);
    ret=mul(ret,pow(p,getk(n,p)-getk(m,p)-getk(n-m,p),pe),pe);
    return ret;
}
il ll C(ll n,ll m){
    if(m<0)return 0;
    ll x=0;
    for(int i=1;i<=o;++i){//crt合并
        ll M=mod/pe[i];
        x=(x+mul(mul(getC(n,m,p[i],pe[i],P[i]),M,mod),inv(M%pe[i],pe[i]),mod))%mod;
    }
    return x;
}

狄利克雷卷积

假设\(h=f*g\),那么\(h(x)=\sum_{ij=x}f(i)g(j)\)

杜教筛

\(\sum_{i=1}^nf(x)\),满足这是个积性函数。

构造两个积性函数\(g,h\)使得\(g*f=h\),而且\(g,h\)可以快速算前缀和

\(S(x)=\sum_{i=1}^xf(i)\)

\(\sum_{i=1}^nh(i)=\sum_{i=1}^n\sum_{d|i}g(d)f(\frac{i}{d})\)

\(\sum_{i=1}^nh(i)=\sum_{i=1}^ng(i)\sum_{j=1}^{\frac{n}{i}}f(j)\)

\(\sum_{i=1}^nh(i)=\sum_{i=1}^ng(i)S(\frac{n}{i})\)

右边\(i=1\)这一项是\(g(1)S(n)\),提出来

\(-g(1)S(n)=\sum_{i=2}^ng(i)S(\frac{n}{i})-\sum_{i=1}^nh(i)\)

拉格朗日插值

从yyb博客里蒯个公式走人了

假装P是一个关于x的n次多项式,我们已经知道了P(i),i∈[0,n]的值。

\(P(x)=\sum_{i=0}^{n}P(x_i)\prod_{j=0,j\ne i}^{n}\frac{x-x_j}{x_i-x_j}\)

x取值连续时可以做到\(O(n)\)(从https://attack.blog.luogu.org/solution-p4781蒯的)

\(x_i\)换成\(i\),现在柿子为\(P(x)=\sum_{i=0}^{n}P(x_i)\prod_{j=0,j\ne i}^{n}\frac{x-j}{i-j}\)

维护关于\(x\)的前后缀鸡\(pre_i=\prod_{j=0}^ix-j,suf_i=\prod_{j=i}^nx-j\)

\(P(x)=\sum_{i=0}^nP(i)\frac{pre_{i-1}suf_{i+1}}{i!(x-i)!(-1)^{x-i}}\)

多项式(部分)全家桶

新的

剩下的好像就算会了考场也推不出

数据结构

好像不用怎么记了啊(flag)。。。最近打太多了尤其是萝卜那一场打了一堆数据结构

放点notice:

  • LCTpushdown不要pushdown到整个LCT的根,只downd

字符串

字符串蛤希

应该打得出来。。。

后缀数组SA

应该打得出来,毕竟打得比较多

namespace SA{
    int x[400010],y[400010],SA[400010],rk[400010],ht[400010],t[400010];
    int st[19][400010],lg[400010];
    il int getLCP(int x,int y){
        if(x==y)return 1e9;
        int l=lg[y-x];
        return std::min(st[l][x],st[l][y-(1<<l)]);
    }
    il vd getSA(){
        int set=400000;
        for(int i=1;i<=N;++i)++t[x[i]=S[i]];
        for(int i=1;i<=set;++i)t[i]+=t[i-1];
        for(int i=N;i;--i)SA[t[x[i]]--]=i;
        for(int k=1;k<=N;k<<=1){
            int p=0;
            for(int i=N-k+1;i<=N;++i)y[++p]=i;
            for(int i=1;i<=N;++i)if(SA[i]>k)y[++p]=SA[i]-k;
            for(int i=1;i<=set;++i)t[i]=0;
            for(int i=1;i<=N;++i)++t[x[y[i]]];
            for(int i=1;i<=set;++i)t[i]+=t[i-1];
            for(int i=N;i;--i)SA[t[x[y[i]]]--]=y[i];
            std::swap(x,y);x[SA[1]]=p=1;
            for(int i=2;i<=N;++i){
                if(y[SA[i]]!=y[SA[i-1]]||y[SA[i]+k]!=y[SA[i-1]+k])++p;
                x[SA[i]]=p;
            }
            if(p>=N)break;set=p;
        }
        for(int i=1;i<=N;++i)rk[SA[i]]=i;
        for(int i=1,j,k;i<=N;++i){
            if(rk[i]==N)continue;
            if(k)--k;
            j=SA[rk[i]+1];
            while(S[i+k]==S[j+k])++k;
            ht[rk[i]]=k;
        }
        for(int i=2;i<=N;++i)lg[i]=lg[i>>1]+1;
        for(int i=1;i<=N;++i)st[0][i]=ht[i];
        for(int i=1;i<=lg[N];++i)
            for(int j=1;j+(1<<i)-1<=N;++j)
                st[i][j]=std::min(st[i-1][j],st[i-1][j+(1<<i-1)]);
    }
}

后缀自动鸡SAM

完全不记得了.jpg

其他东西

转载于:https://www.cnblogs.com/xzz_233/p/10610793.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值