嗯。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
显然暴力枚举每个组的话状态数肯定很多(感觉是 O(n!)O(n!)O(n!) 级别的),肯定炸。
注意到这题是蓝题,所以考虑状压 DP。
令 f(i)f(i)f(i) 为 iii 的所有二进制位为 111 的下标组成的集合。
dp[i]dp[i]dp[i] 表示当前集合 f(i)f(i)f(i) 的兔子全都分好组了,其他还没分组。
令 cont(s)\text{cont}(s)cont(s) 为兔子集合 sss 可以得到的分,则有如下转移方程:
dp[i]=maxf(j)∈f(i)dp[j]+cont(f(i)⊕f(j))dp[i]=\max_{f(j)\in f(i)} dp[j]+\text{cont}(f(i)\oplus f(j))\\ dp[i]=f(j)∈f(i)max dp[j]+cont(f(i)⊕f(j))
显然可以预处理 cont(i)\text{cont}(i)cont(i),转移时可以位运算代替集合运算。
但是这样的话时间复杂度是 O((2n)2)O((2^n)^2)O((2n)2),n=16n=16n=16 时会运行约 2×1092\times 10^92×109,会超时。
注意到有很多无效的枚举,可以优化。
当 f(j)∈f(i)f(j)\in f(i)f(j)∈f(i) 时,对于 iii 所有二进制为 000 的位置,jjj 二进制这个位置一定是 000。
所以对于状态 iii,我们只需要枚举 iii 为 111 的二进制位即可,单次枚举次数为 2popcount(i)2^{\text{popcount}(i)}2popcount(i)。
这样可以减小大量的状态数,经过计算可知总状态数约等于 4×1074\times 10^74×107 个,再乘个配置 jjj 的 nnn 也绰绰有余。
时间复杂度:O(4×107×n)O(4\times 10^7\times n)O(4×107×n)。
其实这个代码还可以优化,可以通过递推来将时间复杂度中的 nnn 去掉,请大家自行尝试。