超快的组合数板子
int fact[N], infact[N];
int power(int x, int k, int p) {
int ret = 1;
while(k) {
if(k & 1) ret = ret * x % p;
k >>= 1;
x = x * x % p;
}
return ret % p;
}
int inv(int x, int p) { //求x关于模p的逆元
return power(x, p - 2, p) % MOD;
}
int C(int a, int b) { //求组合数
return fact[a] * infact[b] % MOD * infact[a - b] % MOD;
}
void init()
{
fact[0] = infact[0] = 1;
for (int i = 1; i < N - 1; i++)
{
fact[i] = fact[i - 1] * i % MOD;
}
infact[N - 2] = power(fact[N - 2], MOD - 2, MOD);
for (int i = N - 3; i >= 1; i--)
{
infact[i] = infact[i + 1] * (i + 1) % MOD;
}
}
void solve()
{
init();
}
例题
思路
一道计算几何和数论的题,可表示出每次轰炸击中的概率,至少需要击中的次数。然后参考二项分布的求法,注意用上篇逆元求组合数板子(这篇)会TLE第8个样例,只能用上边更快的板子才能过。
AC代码
#include<bits/stdc++.h>
#define int long long
#define ld long double
using namespace std;
const int N = 5e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int n;
int R1, R2, r, a, h;
int pp[N], qq[N];
int fact[N], infact[N];
int power(int x, int k, int p) {
int ret = 1;
while(k) {
if(k & 1) ret = ret * x % p;
k >>= 1;
x = x * x % p;
}
return ret % p;
}
int inv(int x, int p) { //求x关于模p的逆元
return power(x, p - 2, p) % MOD;
}
int C(int a, int b) { //求组合数
return fact[a] * infact[b] % MOD * infact[a - b] % MOD;
}
void init()
{
fact[0] = infact[0] = 1;
for (int i = 1; i < N - 1; i++)
{
fact[i] = fact[i - 1] * i % MOD;
}
infact[N - 2] = power(fact[N - 2], MOD - 2, MOD);
for (int i = N - 3; i >= 1; i--)
{
infact[i] = infact[i + 1] * (i + 1) % MOD;
}
}
void solve()
{
init();
cin >> n >> R1 >> R2 >> r >> a >> h;
//需要炸的次数
int ned = h / a;
if(h % a != 0) ned ++;
//特判边界
if(ned > n) { //概率为零
cout << 0 << endl;
return;
}
if(R1 + r >= R2) { //概率为1
cout << 1 << endl;
return;
}
int x = (R1 + r) * (R1 + r) % MOD;
int y = R2 * R2 % MOD;
int p = x * power(y, MOD - 2, MOD) % MOD;
int q = (y - x + MOD) * power(y, MOD - 2, MOD) % MOD;
pp[0] = qq[0] = 1;
for (int i = 1; i <= n; i++)
{
pp[i] = pp[i - 1] * p % MOD;
qq[i] = qq[i - 1] * q % MOD;
}
int ans = 0;
for (int i = ned; i <= n; i++) {
// printf("%lld\n", C(n, i));
int tmp = C(n, i) * pp[i] % MOD * qq[n - i] % MOD;
ans = (ans + tmp) % MOD;
}
cout << ans << endl;
}
int32_t main()
{
int _ = 1;
// cin >> _;
while(_--) solve();
return 0;
}