传统游戏
- 看到题,第一想法是设dp[k][s]dp[k][s]dp[k][s]表示选了kkk个数,当前异或和为sss的方案数,但这样产生一个问题:要如何保证所选的数不重复且无序呢?
- 一种方法是修改状态:我们增设一维iii,dp[i][k][s]dp[i][k][s]dp[i][k][s]表示从≤i\leq i≤i的范围中 (引入“阶段”使决策有序化) 选了kkk个数,当前异或和为sss的方案数。(按任意顺序选数难以得知哪些数被选过,但如果强制按从小到大的顺序选数,便可保证所选的数不重且无序。思路类似背包的状态设计。)
这样可以过掉subtask1subtask1subtask1 - 上面的方法适合nnn大LLL小的情况,然而此题中nnn远小于LLL。我们转化一下思路,从高往低考虑二进制下的每一位,枚举nnn个所选数的这一位上是0还是1,每一位只有2n2^n2n种情况,总时间复杂度O(2nL)O(2^nL)O(2nL):设F[i][lim][sta]F[i][lim][sta]F[i][lim][sta]表示做完了从高往低的前iii位,最大的那个数是否还等于mmm ,从大往小每个数是否等于下一个数(状压) 的方案数,数位DP即可
- 另一种思路是:直接计算不重且无序的方案数不方便,因此先算可重且有序的方案数,再通过容斥搞出不重且无序的方案数。(思路类似简单的博弈题)
- 考虑如何计算可重且有序的方案数:
- 类似 数位DP 的做法,从高位往低位考虑,假设当前做到第iii位。
不难发现,如果一个数的前i−1i-1i−1位还等于mmm的前i−1i-1i−1位 ,那么接下来的一位填什么还会受限制;
然而如果一个数的前i−1i-1i−1位已经小于mmm的前i−1i-1i−1位了,那么接下来所有位填什么都不会受限制。 - 这样一来,如果做完第iii位后,这nnn个数中有某个数的前iii位小于mmm的前iii位,那么可以让其余n−1n-1n−1个数在填第i+1i+1i+1位以及之后的位时,不再考虑异或和为0的限制,然后用这个数把最终的异或和调整为0。
- 因此,我们可以枚举从哪一位开始出现确定小于mmm的数,然后计算方案数。
不妨设在这一位填1后后面几位还有aaa种方案(仅考虑<m<m<m的限制),填0后还有bbb种方案(仅考虑<m<m<m的限制),那么方案数为:∑i=0n−1Cniaibn−1−i[imod2=0]\sum_{i=0}^{n-1}C_n^ia^ib^{n-1-i}[i\space mod\space 2=0]i=0∑n−1Cniaibn−1−i[i mod 2=0](若某个数在这一位确定小于mmm,那么此数的这一位必为0,其余n−1n-1n−1个数仍要保证在这一位上的异或和为0,iii表示在这一位填1的数的个数) - 如此,我们可以在O(nL)O(nL)O(nL)的时间内算出选nnn个数的可重且有序的方案数。但因为要做容斥,所以我们需要知道所有选111~nnn个数的方案数,这样复杂度就是O(n2L)O(n^2L)O(n2L)了。
- 仔细观察,发现式子还能继续化简:
∑i=0n−1Cniaibn−1−i[imod2=0]\sum_{i=0}^{n-1}C_n^ia^ib^{n-1-i}[i\space mod\space 2=0]∑i=0n−1Cniaibn−1−i[i mod 2=0]
=∑i=0nCniaibn−i[imod2=0]−an[nmod2=0]=\sum_{i=0}^{n}C_n^ia^ib^{n-i}[i\space mod\space 2=0]-a^n[n\space mod\space 2=0]=∑i=0nCniaibn−i[i mod 2=0]−an[n mod 2=0]
=∑i=0nCniaibn−i+∑i=0nCni(−a)ibn−i2−an[nmod2=0]=\frac{\sum_{i=0}^{n}C_n^ia^ib^{n-i}+\sum_{i=0}^{n}C_n^i(-a)^ib^{n-i}}{2}-a^n[n\space mod\space 2=0]=2∑i=0nCniaibn−i+∑i=0nCni(−a)ibn−i−an[n mod 2=0]
=(a+b)n+(b−a)n2−an[nmod2=0]=\frac{(a+b)^n+(b-a)^n}{2}-a^n[n\space mod\space 2=0]=2(a+b)n+(b−a)n−an[n mod 2=0]
这样,时间复杂度就是O(nL)了O(nL)了O(nL)了 - 考虑如何用容斥得出答案: