注意事项&错误
- 论有效对拍和测试极限数据的重要性
- 不要局限思维
- 不要被某些神奇的C++调试错误坑
- 不要主观臆断认为一个算法会TLE。——Werkeytom_FTD
- 别老忘记清零标记!
- 用∑合并式子的时候小心特殊情况,特别是当有
T
<
S
T<S
T<S的情况时! 如:
( k − 1 ) m − k m = ∑ i = 1 m − 1 C m i ∗ ( − 1 ) m − i ∗ k i (k-1)^m-k^m=\sum_{i=1}^{m-1}C_m^i*(-1)^{m-i}*k^i (k−1)m−km=i=1∑m−1Cmi∗(−1)m−i∗ki
但当 m = 0 , k = 0 m=0,k=0 m=0,k=0时要加特判!!! - 不要懒得加%&开LL!!!!!!!!!!
- 打题前先把整个程序仔细想一下,别急着!
- 打程序的时候用心点啊!!!别老写错变量啊!!!
- 改了循环变量的时候记得仔细检查一下下面的程序。
- 当题目需要大规模连边时,考虑用中介点代替暴力连。
- 不能太依赖对拍!
- 改数据结构的时候一定要好好检查没有改的部分(merge),老在出问题!
14. >>>>记忆化的时候(特别是杜教筛),能不放hash里就别放,常数++!<<<< - 哈希数组不能删除!
- 判断两数是不是0时(线段树),不能用(!(l1*r1)),因为 ( i n t ) ( 65536 ∗ 65536 ) = 2 32 m o d 2 31 = 0 (int)(65536*65536)=2^{32}\mod 2^{31}=0 (int)(65536∗65536)=232mod231=0;
- 分块时要用 ⌊ n i ⌋ \lfloor\frac{n}{i}\rfloor ⌊in⌋暴力算一些数时,可以先预处理小的,因为大的不会有很多;
- 斜率优化没有等于;
- 在做公式题时,考虑理解式子的意义;【例】
- 当想到一题的分治做法时,考虑是否可以把分治倒过来做,优化常数/代码量 ;【例】
- 优化DP观察变化小的变量,考虑去掉冗余状态,如遇到有差的题目(如极差),考虑用差分优化;【例】
- 判断语句并列式,注意顺序,先判断越界;
- 代价贪心考虑二分判定合法。【例】
- 树上问题与路径相关,优先考虑点分治;
- C公式记得判断 m < n m<n m<n
一些奇怪的吼东西/考前必读
【数论】Min_25筛
【数论】关于斯特林数
【多项式】多项式逆元/开方/取模/多点求值/插值/牛顿迭代/对数/exp/幂
支配树小记
【技巧】浅谈Johnson算法
【技巧】可撤销贪心
【黑科技】用树状数组解决区间修改查询问题
【莫比乌斯反演】非正常套路
【二项式剩余】Cipolla(模意义下开根)
【容斥妙用】快速求积的和
一些容易忘记的公式## 反演
莫比乌斯反演
f
d
=
∑
i
=
1
⌊
n
d
⌋
g
i
d
⇔
g
d
=
∑
i
=
1
⌊
n
d
⌋
f
i
d
∗
μ
(
i
)
f_d=\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}g_{id} \Leftrightarrow g_d=\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f_{id}*\mu(i)
fd=i=1∑⌊dn⌋gid⇔gd=i=1∑⌊dn⌋fid∗μ(i)
f
n
=
∑
i
∣
n
g
i
⇔
g
n
=
∑
i
∣
n
f
i
∗
μ
(
n
i
)
f_n=\sum_{i|n}g_{i} \Leftrightarrow g_n=\sum_{i|n}f_{i}*\mu(\frac{n}{i})
fn=i∣n∑gi⇔gn=i∣n∑fi∗μ(in)
二项式反演
f
n
=
∑
i
=
0
n
(
−
1
)
i
(
n
i
)
g
i
⇔
g
n
=
∑
i
=
0
n
(
−
1
)
i
(
n
i
)
f
i
f_n = \sum_{i=0}^n (-1)^i {n \choose i} g_i \Leftrightarrow g_n = \sum_{i=0}^n (-1)^i {n \choose i} f_i
fn=i=0∑n(−1)i(in)gi⇔gn=i=0∑n(−1)i(in)fi
f
n
=
∑
i
=
0
n
(
n
i
)
g
i
⇔
g
n
=
∑
i
=
0
n
(
−
1
)
n
−
i
(
n
i
)
f
i
f_n = \sum_{i=0}^n {n \choose i} g_i \Leftrightarrow g_n = \sum_{i=0}^n (-1)^{n-i} {n \choose i} f_i
fn=i=0∑n(in)gi⇔gn=i=0∑n(−1)n−i(in)fi
斯特林数反演
f ( n ) = ∑ i = 0 n S ( n , i ) g ( i ) ⟺ g ( n ) = ∑ i = 0 n s ( n , i ) ( − 1 ) n − i f ( i ) f(n)=\sum_{i=0}^nS(n,i)g(i) \Longleftrightarrow g(n)=\sum_{i=0}^ns(n,i)(-1)^{n-i}f(i) f(n)=i=0∑nS(n,i)g(i)⟺g(n)=i=0∑ns(n,i)(−1)n−if(i)
欧拉函数的性质
∑
i
∣
n
φ
(
i
)
=
n
\sum_{i|n}\varphi(i)=n
i∣n∑φ(i)=n
证明在这里
μ \mu μ和 φ \varphi φ的关系
∑
i
∣
n
μ
(
i
)
∗
n
i
=
φ
(
n
)
\sum_{i|n}\mu(i)*\frac{n}{i}=\varphi(n)
i∣n∑μ(i)∗in=φ(n)
证明在这里
TIPS
C++调试
编译选项
-fsanitize=address:检查数组越界 (liunx才能用)
-ftrapv:检查整型越界
gdb相关
p x=1
强制给x赋值
输出调试
#define DEBUG(...) \
{ \
if(1) \
{ \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
} \
} \
注意后面的斜杠不能丢!
调用的时候就直接写DEBUG("QwQ %d",a)
即可,
还有一种方法
#ifdef DEBUG
#define Dprint(...) printf(__VA_ARGS__)
#else
#define Dprint(...)
#endif
这个东西加在头文件,程序里面直接写Dprintf()
即可,
如果编译时加上-D DEBUG
就执行上面的,else执行下面的
gcd
设
x
,
y
x,y
x,y使
gcd
(
x
,
y
)
=
1
\gcd(x,y)=1
gcd(x,y)=1,则:
gcd
(
x
+
y
,
x
)
=
gcd
(
x
+
y
,
y
)
=
gcd
(
x
y
,
x
+
y
)
=
1
\gcd(x+y,x)=\gcd(x+y,y)=\gcd(xy,x+y)=1
gcd(x+y,x)=gcd(x+y,y)=gcd(xy,x+y)=1
Max/Min转化
max
(
a
,
b
)
=
a
+
b
−
m
i
n
(
a
,
b
)
\max(a,b)=a+b-min(a,b)
max(a,b)=a+b−min(a,b)
min
(
a
,
b
)
=
a
+
b
−
m
a
x
(
a
,
b
)
\min(a,b)=a+b-max(a,b)
min(a,b)=a+b−max(a,b)
网格图多源多汇最短路
此方法适用于某一维不是特别多的情况,
考虑分治,考虑跨过分治线的答案,暴力枚举路径经过分治线时的经过哪个点,
这样的复杂度为
O
(
n
log
(
n
)
n
)
O(n\log(n)\sqrt{n})
O(nlog(n)n)(n为格子总数)
带前插入单调栈
维护一个单调栈,兹瓷每次在最前面加一个元素,
也就是说,有一个序列,我们要求每个位置的后缀的单调栈,
从后往前做,对于当前位置,找到当前元素第一次被弹掉的地方t(第一次栈为空),再直接继承t+1的栈。
矩阵树定理
定义一棵树的基尔霍夫矩阵为其度数矩阵-邻接矩阵。即Ci,i=deg[i],Ci,j=-(i和j相连)
那么我们有基尔霍夫矩阵的任意余子式Mi,i的行列式就是这棵树的生成树个数。
Hall定理
一个二分图存在一种完全匹配方案,当且仅当,对于左边任意的集合{S},其右边有边相连的点集{T},满足|S|<=|T|。
FWT
DFT | IDFT | |
---|---|---|
XOR | c[i]=(c[i]+c[i+mid]),c[i+mid]=(c[i]-c[i+mid]) | c[i]=(c[i]+c[i+mid])/2,c[i+mid]=(c[i]-c[i+mid])/2 |
OR | c[i]=c[i],c[i+mid]=(c[i]+c[i+mid]) | c[i]=c[i],c[i+mid]=c[i+mid]-c[i] |
AND | c[i]=c[i]+c[i+mid],c[i+mid]=c[i+mid]) | c[i]=c[i]-c[i+mid],c[i+mid]=c[i+mid] |
看到组合数想多项式!!!
PS:外加一个东西,
设
g
x
=
∑
k
=
0
m
C
2
k
x
g_x=\sum_{k=0}^m C_{2k}^x
gx=∑k=0mC2kx,那么有:
g
x
−
1
+
2
g
x
=
C
(
2
m
+
1
,
x
+
1
)
g_{x-1}+2g_x=C(2m+1,x+1)
gx−1+2gx=C(2m+1,x+1)
易证,
也就说我们现在不仅可以求杨辉三角每一列的和,还可以求每一列偶数/奇数行的和,
妙哉~
类欧几里得
f
(
A
,
B
,
C
,
n
)
=
∑
i
=
1
n
⌊
A
i
+
B
C
⌋
f(A,B,C,n)=\sum_{i=1}^n \lfloor\frac{Ai+B}{C}\rfloor
f(A,B,C,n)=i=1∑n⌊CAi+B⌋
∑
i
=
1
n
⌊
A
i
+
B
C
⌋
=
∑
i
=
1
n
∑
j
=
1
m
[
j
≤
A
i
+
B
C
]
=
∑
i
=
1
n
∑
j
=
1
m
[
j
C
−
B
A
≤
i
]
=
∑
j
=
1
m
n
−
⌊
j
C
−
B
−
1
A
⌋
=
n
∗
m
−
f
(
C
,
C
−
B
−
1
,
A
,
m
−
1
)
\sum_{i=1}^n \lfloor\frac{Ai+B}{C}\rfloor=\sum_{i=1}^n\sum_{j=1}^m[j\leq\frac{Ai+B}{C}]=\sum_{i=1}^n\sum_{j=1}^m[\frac{jC-B}{A}\leq{i}]=\sum_{j=1}^m n-\lfloor\frac{jC-B-1}{A}\rfloor=n*m-f(C,C-B-1,A,m-1)
∑i=1n⌊CAi+B⌋=∑i=1n∑j=1m[j≤CAi+B]=∑i=1n∑j=1m[AjC−B≤i]=∑j=1mn−⌊AjC−B−1⌋=n∗m−f(C,C−B−1,A,m−1)
取模后判定大小
[ c ≤ a % k ] = ⌊ a + k − c k ⌋ − ⌊ a k ⌋ [ c\leq a\%k ]=\lfloor \frac{a+k-c}{k} \rfloor-\lfloor \frac{a}{k} \rfloor [c≤a%k]=⌊ka+k−c⌋−⌊ka⌋