我太弱了.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