D 扔硬币

题目地址:

https://ac.nowcoder.com/acm/contest/5758/D

基本思路:

首先如果是肯定不可能的。
然后我们考虑条件概率,设A为至少有m枚硬币是反面,B为恰好有k枚硬币是正面,那么根据条件概率公式,由于恰好k枚硬币是正面所以显然为,而由于是至少枚硬币是反面,所以应该为所有的情况减去有个反面的情况。综上答案就是

参考代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false)
#define int __int128
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)
#define INF (int)1e18

inline int read() {
  int x = 0, neg = 1; char op = getchar();
  while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  return neg * x;
}
inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}


const int maxn = 1e5+10;
int fact[maxn];
inline int qsm(int x,int n,int mod) {
  int res = 1;
  while (n > 0) {
    if (n & 1) res = res * x % mod;
    x = x * x % mod;
    n >>= 1;
  }
  return res;
}
inline int extgcd(int a,int b,int &x,int &y) {
  int d = a;
  if (b != 0) {
    d = extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
  return d;
}
inline int mod_inverse(int a,int m) {
  int x, y;
  extgcd(a, m, x, y);
  return (m + x % m) % m;
}
inline int mod_fact(int n,int p,int &e) {
  e = 0;
  if (n == 0) return 1;
  int res = mod_fact(n / p, p, e);
  e += n / p;

  if (n / p % 2 != 0) return res * (p - fact[n % p] % p);
  return res * fact[n % p] % p;
}
inline int mod_comb(int n,int k,int p) {
  if (n < 0 || k < 0 || n < k) return 0;
  int e1, e2, e3;
  int a1 = mod_fact(n, p, e1), a2 = mod_fact(k, p, e2), a3 = mod_fact(n - k, p, e3);
  if (e1 > e2 + e3) return 0;
  return a1 * mod_inverse(a2 * a3 % p, p) % p;
}
const int mod = 1e9 + 7;
int n,m,k;
signed main() {
  IO;
  fact[0] = 0, fact[1] = 1;
  for (int i = 2; i < maxn; i++) fact[i] = fact[i - 1] * i % mod;
  int t;
  t = read();
  while (t--){
    n = read(),m = read(), k = read();
    if(m + k > n){
      puts("0");
      continue;
    }
    int sum = 0;
    rep(i,0,m - 1){
      sum += mod_comb(n,i,mod);
      sum %= mod;
    }
    int q = (qsm(2,n,mod) - sum + mod) % mod;
    int ans = mod_comb(n,k,mod) * qsm(q,mod - 2,mod) % mod;
    print(ans % mod);
    puts("");
  }
  return 0;
}