B3903 题解
提供一种支持多次询问的方法。
观察题目,发现可以一定可以将序列
可以这样分类的正确性显然可以证明:首先,题目要求
现在我们将这个问题转化为一个排列问题。可设黑球个数为
公式的意义:将白球有序排列后,将
再特判一些特殊情况,即可正确求出答案。
code:
#include<iostream>
using namespace std;
const int N = 2e5 + 5, mod = 1e9 + 7;
inline int qpow(int a,int b) {
int res = 1;
while(b) {
if(b&1) res = (1ll*a*res)%mod;
a = (1ll*a*a)%mod;
b>>=1;
}
return res;
}
int n, k1, k2, k3;
int jc[N] = {1,1}, inv[N] = {1,1};
unsigned long long x1, val, x, a[N];
int main() {
n = read(), x = readULL(), x1 = x>>1;
for(int i=1;i<=n;++i) {
a[i] = readULL(), jc[i+1] = (1ll * (i+1) * jc[i]) % mod;
if(a[i] > x) { cout<<0; return 0; }
else if(a[i] > x1) ++k1, val = a[i];
}
inv[n+1] = qpow(jc[n+1], mod-2), x -= val;
for(int i=n;i>=1;--i) {
inv[i] = 1ll * inv[i+1] * (i+1) % mod;
if(a[i] > x && a[i] != val) ++k2;
else if(a[i] <= x) ++k3;
}
if(k1>k3+1) cout << 0;
else if(k2 == 0) cout << 1ll * jc[k3] * jc[k3+1] % mod * inv[k3+1-k1] % mod;
else cout << 1ll * jc[k3] * jc[k3+1] % mod * inv[k3+1-k1] % mod * jc[k3-k1+k2] % mod * inv[k3-k1] % mod;
return 0;
}