题意:
表示 有 n
个人,m
句歌词。每个人可以 选择每句歌词唱不唱,不能与他人沟通。
若某句歌词被所有人唱了,或者所有人都没唱,那么这句是失败的,否则是成功的。
每个人都十分聪明,求 唱成功的句的期望取模 1e9 + 7
思路:
首先注意到 句子与句子之间没有办法互相影响(相互独立),因此 答案 是 一句话的期望值 乘以 m
,
由于无法交流,且如果每一个人都唱 “最优方案”,反而 最后一句话都唱不成,
所以 最优方案就应该是:每个人 随机以 pi
的概率唱。
决定 唱或不唱 这一句,由于 n
个人之间没有区别,所以 不同人的概率一定是相等的,因此:
-
唱失败的概率
p_lose
是:p ^ n + ( 1 − p ) ^ n
, -
唱成功的概率
p_success
是:1 - p ^ n - ( 1 − p ) ^ n
,
当p_success
取 最大值 的时候,p = 1 / 2
(可以通过 求导 来推导,此时 p_lose
取最小值)
因此,对于每一句话每个人有 1 / 2
的概率去唱,1 / 2
的概率不去唱,
因此 对于一句话来说 :
-
唱失败的概率为:
(1 / 2) ^ n + (1 / 2) ^ n
, -
唱成功的概率为:
1 - (1 / 2) ^ n - (1 / 2)
,
对于 m
句话最后要记得再乘 m
,最后推导出的公式 就是:
,之后求个 逆元(快速幂求逆元详解)即可。
取余注意事项:
取余 时:
-
超过两个数相乘 时,应该每乘两个数就要取一次
mod
-
取余遇到 减法 时,最好 在减法后面加上
mod
再取余,防止减法变成负数(会非常麻烦,不过本题中不需要)
对了,本题需要开 long long
。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9+7;
int qmi(int a, int b)
{
int res = 1;
while(b)
{
if(b&1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
signed main()
{
int t; scanf("%lld", &t);
while(t--)
{
int n, m;
scanf("%lld%lld", &n, &m);
printf("%lld\n", m * (qmi(2, n) - 2) % mod * qmi(qmi(2, n), mod-2) % mod)<<'\n';
}
return 0;
}