思路
坏了这次没啥思路
转化题意, 求存在多少种数列 \(B\) , 使得 \(B\) 与 \(A\) 中, 每种元素出现的次数相同并且满足 \(A_i \neq B_i\)
是这样转化的吗
你考虑直接算, 但是这样无论如何你要记录每种元素当前的出现次数作为状态, 不可能啊
怎么做比较方便? 看下标签发现可以使用「二项式反演」
你考虑到「钦定」\(k\) 个位置出现的元素不同不好处理, 考虑常见转化, 转化成「钦定」\(k\) 个位置出现的元素相同
「钦定」\(n - k\) 个元素相同的方案数我们记为 \(f(k)\)
考虑 \(f(k)\) 的计算, 显然需要对于每种颜色处理
把 \(n - k\) 个元素分给 \(m\) 种颜色让人联想到背包问题, 那么我们考虑 \(\rm{dp}\) 去做
具体的, 你「钦定」\(n - k\) 个元素相同, 其他的随意排列即可
令 \(dp_{i, j}\) 表示考虑前 \(i\) 种颜色,「钦定」\(j\) 个位置与原序列相同 (序列初始顺序与答案无关, 视作按颜色排序) 时对于相同部分可能的方案数, 记 \(c_i\) 表示颜色 \(i\) 的元素个数
有转移
然后你发现剩下的情况是多重集的排列, 所以容易发现
这个 \(\rm{dp}\) 时处理即可
常见套路
代码
#include <bits/stdc++.h>
using namespace std;#define QwQ01AwA return 0
#define ll long long
#define look_time cerr << 1.0 * clock() / CLOCKS_PER_SEC << '\n'
template <typename T> void ckmax(T &x, T y) {x = max(x, y);}
template <typename T> void ckmin(T &x, T y) {x = min(x, y);}const int N = 2005;
const int mod = 1e9 + 9;
int ksm(int a, int b) {int ans = 1;for (; b; b >>= 1, a = 1ll * a * a % mod) {if (b & 1) ans = 1ll * ans * a % mod;}return ans;
}
int n;
int siz[N], f[N], g[N];
int fac[N], inv[N];void init(int n) {fac[0] = 1;for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % mod;inv[n] = ksm(fac[n], mod - 2);for (int i = n; i >= 1; i--) inv[i - 1] = 1ll * inv[i] * i % mod;
}
int C(int n, int m) {return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}signed main() {ios::sync_with_stdio(0);cin.tie(0);init(2000);cin >> n;for (int i = 1, x; i <= n; i++) cin >> x, siz[x]++;f[0] = 1;for (int i = 1; i <= n; i++) {if (!siz[i]) continue;memset(g, 0, sizeof(g));for (int j = 0; j <= n; j++) {if (!f[j]) continue;for (int k = 0; k <= siz[i]; k++) {g[j + k] = (g[j + k] + 1ll * C(siz[i], k) % mod * inv[siz[i] - k] % mod * f[j] % mod) % mod;g[j + k] = (g[j + k] % mod + mod) % mod;}}memcpy(f, g, sizeof(f));}int ans = 0;for (int i = 0; i <= n; i++) ans = (ans + ((n - i) % 2 ? -1 : 1) % mod * 1ll * f[n - i] % mod * fac[i] % mod) % mod;cout << ans << '\n';QwQ01AwA;
}
总结
\(\rm{dp}\) 求 \(f\) 其实挺常见的
首先发现只能处理相同元素, 需要分配
背包处理分配问题是常见的
「钦定」意义下, 「至多」和「恰好」的转化
第一次见到组合数学中「多重集的排列」