您的位置:首页 > 其它

51nod 1667 概率好题 组合数学+容斥原理

2018-01-17 14:49 357 查看

题意

甲乙进行比赛。

他们各有k1,k2个集合[Li,Ri]

每次随机从他们拥有的每个集合中都取出一个数

S1=sigma甲取出的数,S2同理

若S1>S2甲胜 若S1=S2平局 否则乙胜

分别求出甲胜、平局、乙胜的概率。

(显然这个概率是有理数,记为p/q,则输出答案为(p/q)%(1e9+7))(逆元)

注意 多组数据

T<=5,k1,k2<=8,1<=L<=R<=10^7。

分析

%ymw

代码

#include <bits/stdc++.h>

int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}

typedef long long ll;

const int N = 10;
const int MOD = 1000000007;

int n,m,ans;

int lim1
,lim2
;

int l1
,r1
,l2
,r2
;

int ny[25];

int ksm(int x,int y)
{
int res = 1;
while (y)
{
if (y & 1)
res = 1ll * x * res % MOD;
x = 1ll * x * x % MOD;
y >>= 1;
}
return res;
}

int getC(int n,int m)
{
int ans = 1;
for (int i = 0; i < m; i++)
ans = 1ll * ans * (n - i) % MOD;
ans = 1ll * ans * ny[m] % MOD;
return ans;
}

void dfs(int x,int y,int s,int f)
{
if (x > n + m)
{
if (s < 0)
return;
if (y & 1)
{
ans += MOD - getC(s + n + m + f - 1, n + m + f - 1);
}
else
{
ans += getC(s + n + m + f - 1, n + m + f - 1);
}
ans -= ans > MOD ? MOD : 0;
return;
}
dfs(x + 1, y, s, f);
if (x <= n)
dfs(x + 1, y + 1, s - lim1[x] - 1, f);
else
dfs(x + 1, y + 1, s - lim2[x - n] - 1, f);
}

void pre()
{
ny[0] = ny[1] = 1;
for (int i = 2; i <= 20; i++)
ny[i] = 1ll * (MOD - MOD / i) * ny[MOD % i] % MOD;
for (int i = 2; i <= 20; i++)
ny[i] = 1ll * ny[i - 1] * ny[i] % MOD;
}

int main()
{
pre();
int T = read();
while (T--)
{
scanf("%d",&n);
int tot = 1;
for (int i = 1; i <= n; i++)
{
scanf("%d%d",&l1[i],&r1[i]);
lim1[i] = r1[i] - l1[i];
tot = 1ll * tot * (r1[i] - l1[i] + 1) % MOD;
}
scanf("%d",&m);
for (int i = 1; i <= m; i++)
{
scanf("%d%d",&l2[i],&r2[i]);
lim2[i] = r2[i] - l2[i];
tot = 1ll * tot * (r2[i] - l2[i] + 1) % MOD;
}
tot = ksm(tot,MOD - 2);

int s = -1,a[3];
for (int i = 1; i <= n; i++)
s -= l1[i];
for (int i = 1; i <= m; i++)
s += r2[i];
ans = 0;
dfs(1,0,s,1);
a[2] = 1ll * ans * tot % MOD;

ans = 0;
dfs(1,0,s + 1,0);
a[1] = 1ll * ans * tot % MOD;

for (int i = 1; i <= std::max(n,m); i++)
std::swap(l1[i],l2[i]), std::swap(r1[i],r2[i]), std::swap(lim1[i],lim2[i]);
std::swap(n,m);
s = -1;
for (int i = 1; i <= n; i++)
s -= l1[i];
for (int i = 1; i <= m; i++)
s += r2[i];
ans = 0;
dfs(1,0,s,1);
a[0] = 1ll * ans * tot % MOD;

printf("%d %d %d\n",a[0],a[1],a[2]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: