Airplane Arrangements
这是一道关于概率的好题,主要考思维。老师说的
分析
首先从题目可以看出,\(n,m\) 的数据量是 \(10^6\) 级别的,所以我们只能考虑 $O(nlogn),O(n) $ 和 $ O(1)$ 级别的代码,无疑将 \(DP\) 的可能性排除,因为题目中又要考虑到概率的问题,于是乎,我们便可以采用数学的方法。
方法概括
借鉴了一些观点,我们可以将这一条链变成一个环,即用一个节点连接两端,这样就可以将 \(n\) 个节点变为 \(n+1\) 个而我们只需要考虑多加上的这个节点有没有被坐到即可。
首先我们要判断有以下两个概率
1.一个人向这一个方向走的概率 \(P1\) 为 $ (2(n+1))^m$
2.每个座位空着的概率(\(n+1\) 个座位被坐了 \(m\) 个) 即 \(P2\) 为 \(\frac{n+1-m}{n+1}\)
最后的答案即为 \(P1\) 与 \(P2\) 的乘积(因为考虑第 \(n+1\) 个点空着的概率是 \(P2\) 然后所有人走到它这里的概率为 \(P1\) 所以相乘就是答案)
code
#include<bits/stdc++.h>
#define int long long
const int mod=1e9+7;
using namespace std;
inline int read(){
int t=1,x=0;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') t=-1;
for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
return t*x;
}//快读,纯纯个人习惯,与本题无关
int n,m;
int _pow(int x,int y){
int res=1;
while(y){
if(y&1) res=(res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res;
}//快速幂板子
/*
主要考虑本题要求取模,所以直接pow的话可能会导致直接爆掉,而用快速幂则可以保证每乘一次取模一次,保证不会爆,而且可以用来求逆元。
*/
signed main(){
n=read(),m=read();
//int p1=(n+1-m)/(n+1); 错误示范,这样会丢失很多精度,导致答案偏差过大
int p1=(n+1-m)*_pow(n+1,mod-2)%mod;
int p2=_pow(2*(n+1),m);
cout<<p1*p2%mod;
return 0;
}
end
为什么除法要用逆元?
在除法运算中不可以对分子分母分别取模来进行计算,当 \(a\) 和 \(b\) 足够大时如果强行分别取模的话会导致精度缺失较大,结果就不准确了。
逆元可以用各种方法解决,这里只提供了快速幂的解法,其他的方法可以再学习。

浙公网安备 33010602011771号