P3214 [HNOI2011] 卡农
打表找规律失败了。。。
参考题解第一篇。
其实就差一步的思路。
题意简化:每次在 [1,2n−1] 中选一个数,选 m 次,不可重复选,使得这 m 个数的异或和为 0 ,求方案数(最后答案数除以 m! )。
令 fm 表示选 m 次的方案数。我们尝试得出 f 的递推式。
首先,不考虑重复,答案是 A2n−1m−1 (最后一个数由前 m−1 个数决定)。设前 m 个数的异或和为 k 。接下来看两种违法情况:
- k=0
要减去前 m−1 个数的异或和为 0 的方案数。
解决方案:答案减去 fm−1 。
- k 在前 m−1 个数中出现过
这意味着前 m−1 个数中除去等于 k 的那个数的另外 m−2 个数的异或和为 0 。我们把等于 k 的数拎出来,剩下的 m−2 个数异或和为 0 的可能情况数就是 fm−2 。由于前 m−2 个数和等于 k 的那个数是互异的,故 k 的可能取值只有 2n−1−(m−2)=2n−m+1 种。这个时候我们再把 k 放回剩下的 m−2 个数,插空的方法有 m−2+1=m−1 种。根据乘法原理,这三者之积就是我们多算的方案数。
解决方案:答案减去 fm−2⋅(2n−m+1)⋅(m−1) 。
故递推式为:
fm=A2n−1m−1−fm−1−fm−2⋅(2n−m+1)⋅(m−1)
最终答案为:
ans=m!fm
由于 108+7 是个质数,我们可以用费马小定理求出 (m!)−1 。 A2n−1i 可以预处理。
总复杂度 O(n+m+logMOD)=O(n+m) 。
这道题告诉我们,当我们发现当前方案好像会有不合法的部分时,不要着急放弃该方案,而要想一想能否容斥。像这种递推式较为复杂的题,打表找规律也没法找了。