最近几天刷了几道状压dp与线段树dp,在补题的时候发现了分层图最短路这个知识点之前没有接触过,类似于网络流中的拆点。最近主要在练习一些数论题,我数论接触的不是很久,感觉挺难的。
状态压缩中的几个小技巧
int comb = (1<<(k)) - 1;//
while(comb < (1<<n)){
//总集合为{ 0 到 (1<<n)-1 } , 对大小为k个1的子集进行枚举 comb为子集
int x = comb & (-comb) ,y = comb + x;
comb = ((comb & ~y)/x >> 1) | y;
}
for(int sub = n;sub;sub =(sub-1)&n){
//sub 为 n 的子集
}
int table[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
int popcount(unsigned int x) { // 返回x的二进制中1的个数
int ret = 0;
for(int i = 0; i < 8; i++) {ret += table[x & 15]; x >>= 4;}
return ret;
}
线段树优化的dp 也是比较套路的
大概像是在区间段里进行背包,通过线段树优化快速找到转移的状态
排列组合的隔板法:
a1 + a2 + a3 + a4 + … + ak = n
如果是等式 就要减去一个 :C[n-1][k-1]
l <= a1 <= a2 <= a3 <= … <= ak <= r
如果是不等式就 要就要把 隔板左边那一段的作为一个区间 : C[r-l+k][k]
做cf的时候发现stl要用熟练啊,虽然平时都说不能依赖stl但是如果用不熟练的话真的很吃亏