题解:B3903 [NICA #3] 星空(Hard Version)
提供一种
如果存在一个
如果
设
拿样例举例,
那么限制就是
设
假设已经放好了所有
现在考虑放
根据乘法原理,相乘即可得到答案。
因为每个数互不相同,最后答案要乘上
答案为:
#include <bits/stdc++.h>
#define mkp make_pair
#define fi first
#define se second
#define vec vector
#define eb emplace_back
using namespace std;
#define int long long
const int mod = 1e9 + 7;
signed main() {
int n, X;
cin >> n >> X;
vec<int> a(n + 3);
int Mx = 0;
for (int i = 1; i <= n; i++)
cin >> a[i], Mx = max(Mx, a[i]);
if (Mx >= X) {
cout << "0\n";
return 0;
}
vec<int> fc(n * 2 + 3), ifc(n * 2 + 3);
fc[0] = 1;
for (int i = 1; i <= n * 2; i++)
fc[i] = fc[i - 1] * i % mod;
auto ksm = [](int a, int b = mod - 2) {
int r = 1;
while (b) {
(b & 1) && (r = r * a % mod);
a = a * a % mod;
b >>= 1;
}
return r;
};
ifc[n * 2] = ksm(fc[n * 2]);
for (int i = n * 2 - 1; i >= 0; i--)
ifc[i] = ifc[i + 1] * (i + 1) % mod;
auto Cc = [&](int n, int m) -> int {
if (n < 0 || m < 0 || n < m) return 0;
return fc[n] * ifc[m] % mod * ifc[n - m] % mod;
};
if (__builtin_popcountll(X) == 1) {
// 计算二进制下 1 的个数
cout << fc[n] << '\n';
return 0;
}
auto tmp = X, ls = 0ll;
while (tmp - (tmp & -tmp))
ls = tmp, tmp -= tmp & -tmp;
ls -= tmp;
int A = 0, B = 0, C = 0;
for (int i = 1; i <= n; i++)
B += (a[i] == tmp), A += (tmp > a[i] && a[i] > ls);
C = n - A - B;
int t = C + 1 - B;
int ans = Cc(C + 1, B) * (A ? Cc(A + t - 1, t - 1) : 1) % mod;
ans *= fc[C] * fc[B] % mod * fc[A] % mod;
ans %= mod;
cout << ans << '\n';
}
有
设第
我们不太会做
得到答案: