这次比赛的T1是原题,但是我还是没有想到。
T1:设f[i]表示第i个障碍为当前路线第一个经过的障碍的方案数,那么我们考虑容斥求f。
考虑用(0,0,0)走到i的总方案数减去经过其他障碍的方案数,那么我们可以枚举经过的第一个障碍j,则f[i]=(0,0,0)到i的方案数-f[j]*j到i的方案数。
最终求答案得方法和上面同理。
总结:对这一类组合dp题,我们经常要指定类似于“第一个”的点,以此达到降维或化简的目的。
T2:我们用一条长度为m,宽度为k的扫描线从上往下扫整个矩阵。设bitset数组s[i][j]表示i这个值当前在j列是否有出现过,g[i][j]表示从(i,j)这个位置往下k位是否有与a[i][j]相同的值。
每次下移的时候,我们先加入第i+k行的数。在加入这些数时,我们求每个j在bitset上的前驱和后继,然后利用前驱和后继判断当前加入的这个数会对那些f产生影响。注意这里有影响的f是一个区间,所以我们用差分。这个很好推。
然后再删除第i行,这时我们要用g来判断一下当前列是否已经没有a[i][j]这个值了。若没有,则从bitset中删去它。此时和上面一样,判断会对那些f产生影响,同样用差分来区间修改。
最后求一遍前缀和就可以了。
注意这里为了求前驱和后继,我们需要打人工bitset。bitset的原理就是把一个有很多位的二进制数每三十二位压一压,这个可以手动实现。在查询的时候我们可以一块一块枚举,这样就节省了很多时间了。
T3:通过找规律发现(然而我不会找)。
当平方之后,我们可以把正负号去掉,然后就变成了。
对于每一个i,(1<=j<=i)。
因为在i个中选j个,再在另外的i个中选i-j个,那么就相当于在2i中选i个。因为j>=1,所以要-1。
这样就可以O(nlogm)做了。
总结:关键还是要学学逆矩阵。