2019金华正睿集训Day1-Day3

Day1Day1-概率与期望

知识点整理

• 独立事件:互相不影响的事件,满足 P(AB) ⁣= ⁣P(A) ⁣ ⁣P(B)P(AB)\!=\!P(A)\!\cdot\!P(B)
• 对于独立事件,我们有 E(AB) ⁣= ⁣E(A)E(B)E(AB)\!=\!E(A)\cdot E(B)
i=0n ⁣xi ⁣= ⁣1xn+1x1\sum_{i=0}^{n}\!x^{i}\!=\!\frac{1-x^{n+1}}{x-1}
i=0 ⁣xi ⁣= ⁣1x1\sum_{i=0}^{\infty}\!x^{i}\!=\!\frac{1}{x-1}
E(X)=i ⁣P(X ⁣= ⁣i) ⁣ ⁣iE(X)=\sum_{i}\!P(X\!=\!i)\!*\!i
• 期望的线性性:E(X ⁣+ ⁣Y) ⁣= ⁣E(X) ⁣+ ⁣E(Y)E(X\!+\!Y)\!=\!E(X)\!+\!E(Y)
• 对于离散变量 X,P(X ⁣= ⁣K) ⁣= ⁣P(X ⁣ ⁣K) ⁣ ⁣P(X ⁣ ⁣K ⁣ ⁣1)P(X\!=\!K)\!=\!P(X\!\leq\!K)\!-\!P(X\!\leq\!K\!-\!1)
• 1. 有 n 个随机变量  ⁣X ⁣[1n] ⁣\!X\![1…n]\!,每个随机变量都是从  ⁣1S ⁣\!1…S\! 中 随机一个整数,求 Max(X ⁣[1n])Max(X\![1…n])的期望
• 2. 概率为 p 的事件期望  ⁣1p ⁣\!\frac{1}{p}\! 次后发生

总结

在做和期望有关的题目时,总体思路我觉得和dp很像,考虑事件的所有情况,并考虑相应的计算方法。通过对随机变量巧妙的定义达到解题的的效果。

要谨慎考虑每种事件发生的概率,概率均等是重要的条件。
要谨慎判断一个事件是否是独立事件,不要想当然。对于 P(AB) ⁣= ⁣P(A)P(B)P(AB)\!=\!P(A)P(B)E(AB) ⁣= ⁣E(A)E(B)E(AB)\!=\!E(A)E(B) 这两个特性要在确定为独立事件后使用
小技巧 :x ⁣= ⁣i=1x ⁣1x\!=\!\sum_{i=1}^{x}\!1 通过这样转化后再整理式子有时会有奇效


Day2Day2-各种分治,图论,字符串

知识点整理

分治:

主要思想是通过将区间分成两个区间,来将问题分成两个子问题,大事化小

二分

二分就是对答案分治
重点是怎么快速的check

整体二分

把答案和修改操作一起二分,通过处理子问题的顺序来保证处理答案时的正确性

CDQ分治

把 [L,R] 分成 [L,mid] 和 [mid+1,R],考虑左边对右边的贡献。
好处在于在面对题目时通常可以将形似i<ji<j的约束略去

点分治

其实就是树上分治?
选择重心作为根是常见的小策略,然后对每一个子树进行分治。
因为重心保证每一棵子树的大小 ⁣2n\leq\!\frac{2}{n} 因此可以保证时间复杂度

时间分治

老师只讲了一句话:就是对时间进行分治?(雾)

图论:

(感觉图论偏简单?)

BFS

BFS染色,很多后面的题目都要用的东西
遇到边权只有1或2的时候把边权为二的边拆边

Dijkstra

原理:当前 d[x] 最小的 x 一定已经确定了最短路
不能处理负权
堆优化可以到O(nlogn)O(nlogn)

SPFA

队列优化的Bellman-Ford
用一个队列维护有哪些点等待更新
每次取出一个点 x 去更新所有出边 (x,y,w),如果 y 被更新了就压入队列
时间复杂度:O(nk)O(nk)
菊花图秒卡。。
(关于SPFA,它已经死了)
用处:
1.1.判负环:
判断最短路的边数是否>n
判断一个点是否入队超过 n 次
原理为加入超过n条边必然有负环
2.2.差分约束:
对于 (x,y,w),d[y]<=d[x]+w
最短路问题可以给出这一类不等式的最大解(最小解)
(用SPFA是因为Dijkstrla不能有负权)

Floyd

最稳定的O(n3)O(n^3)算法
可以算任意两点最短路
原理是基于dp的:
F(K,X,Y)F(K,X,Y) 表示 XXYY 的路径中,满足路路径上的点的标号 都不超过 KK 的最短路径。F(K,X,Y)=Min(F(K1,X,Y),F(K1,X,K)+F(K1,K,Y))F(K,X,Y)=Min( F(K-1,X,Y),F(K-1,X,K)+F(K-1,K,Y))

次短路

一条次短路一定至多经过一条非最短路图上的边
先跑两边单源最短路(头一遍,尾一遍),然后处理非最短路图上的边

最短路变种

每次删一个点后询问最短路
每次删一条边后询问最短路
总体思路和次短路差不多

Prufer序

可以一一对应的把一棵树变成一个序列
每次选择树上标号最小的叶子,删掉它,将与它相连的那个点的标号加到序列里,直到只剩下2个点
Ps:Ps : 由此得:n 个点的无根树个数为 nn2n^{n-2}

Tarjan

(我发现我快不会写Tarjan了)
(然而老师上课还跳了)
对整个图进行 dfs,设dfn[x] 表示点 x 是第几个被搜到的
low[x] 表示 x 通过非返祖边,且至多通过一条非树边能到达的最小dfn
用处:求割点割边,强连通分量
复杂度:O(n)O(n)

欧拉回路

定义:一张有向图,一条经过每条边恰好一次的回路
(哈密尔顿回路是经过每个点一次)
必要条件:
1.这张图是个强连通分量
2.每个点的出度等于入度
3.可以发现这两个条件同时也是充分的
(充分即有这两个条件,则必有欧拉回路)

二分图

可以分成两部分,使得这两部分内部没有边的图
一个图是二分图则图内无奇环
判奇环:BFS染色
判偶环:若两个奇环有一条边,则存在偶环
最小顶点覆盖:选最少的点覆盖所有边
|二分图最小顶点覆盖|=|二分图最大匹配|
最大独立集:选最多的点使得它们两两没边相连
|二分图最大独立集|=总点数-|二分图最小顶点覆盖|
(关于二分图匹配,请右转百度 匈牙利算法 or dinic)在这里插入图片描述
(搬课件一时爽)
Hall定理:
SS 是左边点的一个子集(二分图将点分成两边),设 N(S)N(S)SS 所有点邻居的并集,则一个二分图存在完美匹配的充要条件是:对于所有 SSS<=N(S)|S|<=|N(S)|

字符串:

(SA,SAM是真的毒瘤!)

Hash

课件上老师打了叹号!然后跳了?

KMP

(又一个快不会写的东西)
KMP是利用之前已经部分匹配这个有效信息,让模式串尽量地移动到有效的位置。
设 next 数组为除当前字符外的最长相同前缀后缀
其算法流程如下:
假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置
如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j - next [j] 位。
换言之,当匹配失败时,模式串向右移动的位数为:失配字符所在位置 - 失配字符对应的next 值,即移动的实际位数为:j - next[j],且此值大于等于1
这也意味着在某个字符失配时,该字符对应的next 值会告诉你下一步匹配中,模式串应该跳到哪个位置。
复杂度:O(n+m)O(n+m)
(设S长度为n,P长度为m)

()(以下开始搬课件)

后缀数组

给定一个串 s[1…n],将所有后缀排序
rk[i]:s[i…n] 的排名
sa[i]: rk 为 i 的后缀是哪个
倍增+归并排序实现
height[i]:S[sa[i]…n] 和 S[sa[i+1]…n] 的LCP
height[i]>=height[rk[sa[i]-1]]-1
基本操作:
LCP(X,Y)=Min(H[rk[x]]…H[rk[y]-1])
最长重复子串
不可重叠最长重复子串
本质不同的子串个数
求 S[l…r] 的出现次数

后缀自动机

后缀树:将每个后缀插入 Trie 中得到一个 Trie 树,然后缩掉所有只有一个儿子的点
我们用 fail[x] 表示 x 在后缀树上的父亲
x 代表了一系列子串:这些串的长度是 [len[fail[x]]+1…len[x]],左端点的集合是Right(x):x 子树里有哪些后缀
go[x][c]:x 代表的串左边加上 c 后得到的串是哪个结点
len[go[x][c]]>=len[x]+1
构造:每次往前加点

由于太过毒瘤请谨慎食用代码
在这里插入图片描述
复杂度:
结点数为 O(N)
边数为 O(N)

基本应用:
(本质不同 通俗的说即 长的不一样)
求本质不同的子串个数
求每个前缀/后缀的本质不同的子串个数
求两个串 S,T 的最长公共子串
求LCP(S[i…n],S[j…n])
求第 K 小子串的值(EXT:支持多次询问,每次输出长度)
求一个子串的出现次数
求不重叠最长重复子串

总结

分治和图论思路感觉都还能理解,但细节和代码实现还需要细细品味,最好是写几道题练手。
分治整体有点模式化?
不过处理跨mid的信息有点繁琐(怎么感觉天天分类讨论)
图论我觉得重点是建立模型,以及对一些性质的思考
kmp讲的有点浅。。本来期待着AC自动机的。。
SA和SAM两个巨坑只能之后填了


Day3Day3-组合计数

说是组合计数。。
其实就提了一下欧拉函数。。其他全是容斥。。
(基本挂机)

欧拉函数

1~n之间与n互质的数的个数(课件上就这一句话)

//线性筛1~n的欧拉函数
inline void euler(int n)
{
    memset(vis,0,sizeof(vis));
    memset(prime,0,sizeof(prime));
    memset(phi,0,sizeof(phi));
    int tot=0;
    phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(vis[i]==0) {
            vis[i]=i;
            prime[++tot]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=tot&&prime[j]*i<n;j++)
        {
            if(prime[j]>vis[i] ) {
                break;
            }
            vis[i*prime[j]]=prime[j];
            if(i%prime[j]) {
              phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
            else phi[i*prime[j]]=phi[i]*prime[j];
        }
    }
}

容斥原理

容斥原理是一种重要的组合数学方法,可以让你求解任意大小的集合,或者计算复合事件的概率。

容斥原理可以描述如下:

列出题目中的n个条件。
求满足这n个条件中每一个的方案的个数。 枚举这些条件的所有2^n个集合。
考虑一个集合x,令不满足x中所有条件的方案有A个。如果x的大小是奇数,给答案减去A,不然给答案加上A。

另一种理解方法:

要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个集合相交的部分,再加回所有三个集合相交的部分,再减去所有四个集合相交的部分,依此类推,一直计算到所有集合相交的部分。

上述过程转化为数学公式如下:
A[1...n]A[1...n]为题目给出的nn个条件

在这里插入图片描述
我们设BBAiAi的所有集合,那么可以写的更简洁
在这里插入图片描述
关于容斥的其它内容点这里

补集思想

正难则反。 满足条件的=全部的-不满足条件的。 容斥原理可以看成补集思想的一部分
如:
连通图的数量=图的总数-不连通图的数量。
欧拉图的数量也能相同的方法计算

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章