觉得有什么错误的地方烦请提出!
绝对不咕咕咕!!!
k-nim
- k-nim的必败状态:所有子游戏的(SG)值的每一位的(1)的个数都被(k+1)整除
阶梯Nim
$$color{pink}{link}$$
群论三连
设(G)是目标集([1,n])上的一个置换群,(E_k)是([1,n])在(G)的作用下包含(k)的等价类,(Z_k)是使(k)不动的置换类,(C(pi))在置换(pi)下目标集的不动点个数,(m(pi))置换(pi)的循环节个数,(L)是目标集等价类的个数
具体点:(Z_k)是保持元素(k)不变的置换集合,(E_k)是(k)通过(G)中的置换可以得到的元素集合,等价类是元素经过置换可以变成一样的元素集合,可以想象一个无向图的环。
轨道-稳定集定理
(Burnside)定理
- 文字描述:(1)到(N)在置换群作用下等价类的个数,等于每个置换的不动点个数的平均数。
(Polyacute a)定理
- (k)是可染的颜色数量
一些的并不懂的复杂度证明(积分学的烂
-
枚举(1-2^n)每个数的二进制子集
用这种方法
for(int s=t;s;s=(s-1)&t)
复杂度:(O(3^n))
-
(O(sumlimits_{kmid n}sqrt k))
[=Oleft( sum_{1le ile sqrt{n}}{sqrt{i}+sqrt{frac{n}{i}}} ight) =Oleft( int_1^{sqrt{n}}{dxleft( sqrt{i}+sqrt{frac{n}{i}} ight)} ight) =Oleft( frac{8n^{frac{3}{4}}}{3} ight) =Oleft( n^{frac{3}{4}} ight) ]
二项式反演
以前没有认真想过,从这个方向对普通容斥套式子可能更加方便。
式子的对称性很强,另一个方向可能更加常见
后面这个可以卷
证明一下第一个式子了口胡开始
具体思路是容斥原理,不涉及代数证明,因为我觉得从组合角度说更便于理解。
设有一个集合(S),其中的每个元素都有若干个性质(p),一共存在(n)个性质。
设至少有性质(p_i)的元素的集合为(A_i)
分别定义:
其中({c})是任意的一个长度固定的递增序列。
容易发现,(f_i,g_i)的值并不是定值,所以再添加一个定义,让集合变得特殊一些,让这两个值变成定值就行了。
暴力推式子
然后把(f_i)带进去
然后推(f_n)也是差不多的
原根
若(g)是(m)((m)是质数)的原根,则(g^0,g^1,dots,g^{varphi(m)-1})遍历(mod m)的最小剩余系。
检验(g)是否为原根,把(m-1)分解质因数得到每个质因子(p_i),若(exists g^{frac{m-1}{p_i}}equiv 1 pmod m),则(g)不是原根
一般来说我们求原根从(2)开始枚举就可以了,因为原根一般比较小。
斯特林数
- 一些公式
来个组合的证明吧,会比较舒服。
将(n)个有标号球放到(x)个有标号的盒子的方案数是(x^n)
将(n)个有标号球放到(x)个有标号的非空盒子的方案数是({n race x}x!)
那么按照组合的意义有
注意这个东西进行二项式反演可以得到一个式子
这东西可以卷,推导看这里
- Stirling公式
用来求(n!)的近似值,在(n)比较大的时候准确值高
奇偶性
一式比较简单,直接(lucas)定理搞一下就可以了。
一位一位向上讨论就行了,所有的位必须是(n_ige m_i)
斯特林数就麻烦一点了,这里的思路是sdchr大佬的
首先由斯特林数的通项,我们构造一个和(Ta)奇偶性一样的数列
然后数形结合
在对应位置连边后我们发现(p_{n,m})就是从((0,0))走到((n,m))的方案数。
发现绿边一定会走(m)次,红边一定会走(n-m)次,于是统计一下红边的方案数。
发现一共有(d=lfloorfrac{m+1}{2} floor)次机会走红边(奇数行可以走),每次可以走任意长度
于是转换成了把(n-m)分成(d)段的方案数,插一下板就搞定了,方案数为(inom{n-m+d-1}{d-1})
拉格朗日差值法
现在有(n)个点(x_i,y_i),可以唯一的确定一个多项式。
则原多项式为
化简就是系数表示法了,不过一般还是用来求点值,复杂度(O(n^2))
自然数幂级数之和
方法1 拉格朗日差值
可以预处理((x_1,T_k(x_1)),(x_2,T_k(x_2)),dots,(x_k,T_k(x_k)))这(k)个点,然后进行差值。
注意到
分母上面对同一个(n)可以预处理前缀积和后缀积,下面的连续的乘法,左右都是(1 imes2 imes dots),因为选择的(x)的值在整数上连续,于是复杂度是(O(k))的。
方法2 Stirling展开
预处理一下也是(O(k))的了,(n)比较大的话组合数用计算式算。
提一下这个组合恒等式
其实就是(Pascal)三角形的一列和,把这一列放到右边去加加减减就可以了。
具体点说,把计算式变一下
然后都带进去
减到最后发现是(0)
子集和
其实是快速莫比乌斯变换(FMT)及其反演的一个小trick吧。
考虑定义一个
然后对一个(|U|=n)的全集来说,求出所有子集的这个东西的复杂度暴力枚举子集是(O(3^n))的,然后有一种(O(2^nn))的优秀做法。
定义
然后考虑递推,显然有(hat{f_S}^{(0)}=f_S,hat{f_S}^{(n)}=hat{f_S}),分别是递推初始值和递推目标。
若(Sigcup{i}=varnothing),则有
写成代码非常简单
for(int i=1;i<1<<n;i<<=1)
for(int s=0;s<1<<n;s++)
if(s&i)
f[s^i]+=f[s];
泰勒公式
- 用多项式函数去逼近光滑函数
后缀数组
- (LCP(i,j)=min(LCP(i,k),LCP(k,j)),forall 1le ile kle jle n),这个下标是针对字典序的。
- (h(i)ge h(i-1)-1),这个是针对原位置的。
偷了一份快读的板子
namespace io
{
const int SIZE=(1<<21)+1;
char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];
int f,qr;
// getchar
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
// print the remaining part
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
// putchar
inline void putc(char x){*oS++=x;if(oS==oT)flush();}
// input a signed integer
template <class I>
inline void read(I &x)
{
for(f=1,c=gc();c<'0'||c>'9';c=gc()) if(c=='-') f=-1;
for(x=0;c<='9'&&c>='0';c=gc()) x=x*10+(c&15);x*=f;
}
// print a signed integer
template <class I>
inline void print(I &x)
{
if(!x)putc('0');if(x<0) putc('-'),x=-x;
while(x)qu[++qr]=x%10+'0',x/=10;
while(qr)putc(qu[qr--]);
}
//no need to call flush at the end manually
struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::read;
using io::putc;
using io::print;
支配树
-
不会证明
-
对于一个源点为(r)的有向图的点(w),若(d)点满足删去(d)点后(r)无法到达(w),称作(d)支配(w),(d)是(w)的支配点。
-
在支配(w)的点中,如果一个支配点满足(i ot=w)被(w)剩下所有的支配点(除(w)自己),那么这个(i)被称为(w)的最近支配点,记作(idom(w)),(idom(w))向(w)连边形成的树即为支配树。
-
(DAG)的支配树非常好求,直接按照topo排序增量法构造即可。
-
半支配点:
对图DFS求出dfs树中每个点的dfs序(dfn)
对一个点(w),存在一个点(x),满足(x)到(w)有一条路径,路径上的任意一点(y)(除去(x)和(w))满足(dfn(y)>dfn(w)),称(x)为(w)的半支配点,记作(semi(x))
删掉非树边,连边((semi(w),w)),不改变支配关系。
-
求半支配点
对点(w),遍历反边((x,w))对应的(x)
- 若(dfn(x)<dfn(w))且(dfn(x)<dfn(semi(w))),(semi(w)=x)
- 若(dfn(x)>dfn(w)),取所有满足(dfn(y)>dfn(w))且(y)是(x)的祖先点(y),用(semi(y))尝试更新(semi(w))
-
求支配点
对于一个点(w),找到路径(w)到(semi(w))路径(不包括(semi(w)))上(dfn(semi(x)))最小的一个点(x)
- 如果(semi(x)=semi(w)),则(idom(w)=semi(w))
- 否则(idom(w)=idom(x))
-
实现
采用带权并查集实现,具体细节还是有一点的Code
二分图
-
最小路径覆盖
给定有向图(G=(V,E)),设(P)是(G)的一个简单路(不相交)的集合。如果(V)中所有顶点恰好在(P)的一条路上,称(P)是(G)的一个路径覆盖。
把(V)中每个点拆成两个,设二分图最大匹配为(C),那么(|P|_{min}=|G|-|C|),即最小路径覆盖=顶点数-最大匹配数。
感性理解:
显然 路径的个数+每个路径中边的数量=总点数,总点数不变,于是最大化边的数量,在拆点后的二分图中形成一个匹配等价于连上了一条有向边,于是就可以了。
-
二分图最小点覆盖
对二分图(G),求一个最小点集(S),使得图中任意一条边都有至少一个端点属于(S)。
(Kddot onig)定理:二分图最小点覆盖的点数等于二分图最大匹配包含的边数
构造:
- 求出最大匹配
- 从左边每个非匹配点找增广路,标记访问节点。
- 取左边未标记点,右边标记点
-
二分图最大独立集
对二分图(G),求一个最大点集(S),使得点集任意两点都没有边相连。
- 无向图的最大团等于其补集的最大独立集
- 二分图(G)最大独立集的大小等于(|G|-)最小点覆盖大小
最大权闭合子图
-
闭合图
定义一个有向图(G=(V,E))的闭合图是该有向图的一个点集,且该点集的所有出边都还指向该点集。
-
最大权闭合子图
给每个点(v)一个点权(w),最大权闭合子图是点权和最大的一个闭合图。
-
求最大权闭合子图
构造图(G'=(V',E')),方法如下
(V'=Vcup{s,t})
(E'=Ecup{(s,v)|vin V,w_v>0}igcup{(v,t)|vin V,w_v<0})
然后网络流图的容量为
(c(u,v)=infty,(u,v)in E,c(s,v)=w_v,w_v>0,c(v,t)=-w_v,w_v<0)
这里直接抄了论文的
然后画了图可以形象理解理解
求出图(G')的最小割后的(S)集即为(G)的最大权闭合子图
-
假证明
设(S)图的点权和为(C=C_1+C_2),其中正点权为(C_1),负点权为(C_2)。设割集的边权和为(W=W_1+W_2),正边权(与(S)相连的被割掉的边)和为(W_1),负边权和为(W_2)。注意:(C_2)在数值上是负的,(W_2)是正的。
负点割给(S)要断掉与(T)相连的边,所以(C_2+W_2=0),有(C+W=C_1+W_1),因为右边为正点权和是定值,所以最小割最小化(W)就把(C)最大化了。
上下界网络流
-
无源汇可行流
- 要求流量守恒
- 要求流量满足上下界
建图方法
-
对(E(u,v,l,r)),建(E'(u,v,r-l))
-
对每个点定义(d_i=sum f(u,i)-sum f(i,v)),即流入减去流出。
然后对(d_i>0),建(E'(ss,i,d_i))
(d_i<0),建(E'(i,tt,-d_i))
(ss,tt)是新建的超级源点与超级汇点
感性理解
对每个点先把下界给流了,然后不平衡的通过超级源or汇点强行补。于是最后判断是否有可行流就是看是否这些边流满了。
错位排列
额今天看了13年的容斥的那篇论文,才明白自己之前学的容斥没有一点技巧性可言,也终于明白了大家说的一下沙茶容斥是怎么一回事情
先说说容斥吧
可以用来求并集
可以用来求交集
一般交集转化过去会比较好求
- 一般化的容斥原理,若
则
对于(supseteq)也成立
-
统计一个满足(p_i ot=i)的长度为(n)的排列的数量。
(S_i)代表(p_i ot=i)这个条件
然后答案就是
[egin{aligned} igcap_{i=1}^n S_i&=n!-sum_{i=1}^n(-1)^{i-1}(n-i)!inom{n}{i}\ &=n!sum_{i=0}^nfrac{(-1)^i}{i!} end{aligned} ]
姬酸姬盒小技巧
- 形如(ax+by+cle 0)的式子的方向向量有((-b,a))。你可以发现(b)的正负是决定半平面是在直线上面还是下面的。
多点LCA
orz huyufeifei
(k)个点LCA的最深点是dfs序相邻两点的LCA
最浅点是dfs序最远两点的LCA
NoiLinux 使用
对拍
#include <cstdio>
#include <cstdlib>
int main()
{
for(int i=1;i<=100;i++)
{
system("g++ data.cpp -o data");
system("./data");
system("g++ Dew.cpp -o Dew");
system("./Dew");
system("g++ bf.cpp -o bf");
system("./bf");
if(system("diff -bB Dew.out bf.out"))
{
printf("error in %d
",i);
return 0;
}
system("sleep 1");
}
return 0;
}