题意
甲乙进行比赛。
他们各有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。
分析
代码
#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[N],lim2[N];
int l1[N],r1[N],l2[N],r2[N];
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]);
}
}