P3214 [HNOI2011] 卡农

形式化题意

\(1~n\) 个数,你可以从中选一些数形成一个组合(组合不能为空),然后将一些组合合在一起形成一个大组合,并要求大组合中的每个数都出现偶数次。

step 1

考虑偶数,我们想到异或操作,看到组合套组合,我们想到装压,两个一叠加,就成了第一步,将组合抽象化,变成一个状态,而偶数就是所有状态异或和为0

step 2

考虑到是组合套组合,那么状态便被锁的很死,所以尝试变成排列套组合,最后除序即可

step 3

排列套组合变成了我们熟悉的装压 \(dp\),可是由于状态太大,且转移未知,所以需要一个新的状态以去除以上问题,考虑到目标状态是要为 0,所以将 \(dp\) 状态设为以当前组合结尾且状态异或和为 0 的方案数,那我们如何来却定当前状态与前面的异或和为 0 呢?我们可以设当前状态为前面的状态的异或和,那么考虑转移

step 4

其实既使这样转移也很复杂(这个要是不信,你自己正着做一遍吧),考虑用容斥,那么将分为一下两点:

1. 全部的方案数

考虑到由于当前的状态有前面的状态来得到,并且是唯一指定,所以只要考虑前面的编排,由于是排列套组合,所以是 \(A_{2^n-1}^{m}\) (这个没啥好说的)

2. 不合法的方案数

不合法的有两种:

  1. 在当前状态之前就已经结束了,那么当前状态肯定无法结束,因为组合一定要选,所以这里要减去的方案数为 \(f_{i-1}\) 即在 \(i-1\) 就已经结束了的
  2. 很奇怪,为什么只要减去 \(f_{i-1}\) 的呢,因为这里还要剪掉一些,以上问题来看,如果在 \(i-2\)(这个只是瞎列数) 的时候结束那么到 \(i\) 这里必然存在重复,所以这种不合法就处理重复(不要听我瞎逼逼,这里只是解释一下上面的,下面的才是重点),那么除了以上问题的角度,还有一个是如果出现重复,必然删掉两个数后任然是一个完整的状态(即可以用 \(f\) 表示的状态),所以这种不合法的方案首先有一个 \(f_{i-2}\),那么会有多少种与前面的重复的可能?有 \(i-1\) 种,最后有多少重复的数的可能呢?有 \(2^n-1 -\) \((i-2)\) 为什么要减 \(i - 2\) 因为前面有 \(i - 2\) 个不与它相同,不然早就判掉了,只有删掉,才不会判重,那么这题就结束了。

step 5

真的结束了吗?其实一直遗留了一个问题,就是排列数怎么算,由于 \(2^n-1\) 的最终结果过大,不肯能用常规来做,但是我们可以用递推来解,考虑到排列数的式子是:

\(\frac{n!}{(n-k)!}\)

相当于是每 \(k + 1\) 整个式子要乘上一个被分母释放出来的 \(n - k + 1\),所以递推求解,这下真完了(除非你没听懂我的 \(dp\) 的状态设计,好像除序也没说,不过我觉得是个做题者(指做这道题的人),应该都会吧)

code

#include <iostream>

using namespace std;
using ll = long long;

const int MaxN = 2e6 + 10, mod = 1e8 + 7;

ll qpow(ll a, ll b) {
  ll res = 1;
  for (ll i = 1; i <= b; (b & i) && (res = res * a % mod), a = a * a % mod, i <<= 1) {
  }
  return res;
}

ll f[MaxN], ani[MaxN], n21, n, m, ma = 1;

int main() {
  cin >> n >> m, f[f[0] = 1] = 0, n21 = ((qpow(2, n) - 1) % mod + mod) % mod, ani[ani[0] = 1] = n21;
  for (int i = 2; i <= m; i++) {
    ma = ma * i % mod;
    ani[i] = ani[i - 1] * (((n21 - i + 1) % mod + mod) % mod) % mod;
    f[i] = ((((ani[i - 1] - f[i - 1]) % mod + mod) % mod - (f[i - 2] * (i - 1) % mod * ((n21 - i + 2) % mod + mod) % mod) % mod) % mod + mod) % mod;
  }
  cout << f[m] * qpow(ma, mod - 2) % mod << endl;
  return 0;
}

最短的代码,最无语的思路,这思路我打死都想不到

posted @ 2024-08-03 11:18  yabnto  阅读(20)  评论(0编辑  收藏  举报