首先發出題目鏈接:
鏈接:https://ac.nowcoder.com/acm/contest/882/A
來源:牛客網
涉及:排列組合數學
點擊這裏回到2019牛客暑期多校訓練營解題—目錄貼
題目如下:
說實話,這次出題人的腦洞真大
題目意思解釋一下:有一個環,上面有n個點,分別是從0到n-1
從0號點出發,然後隨意走,每走到一個地方就拿起此位置標記(剛開始每個點都有標記),然後求所有點走完後,最後落腳到m點的概率
注意:題目中還說明了按樣例順序最後落到每個點的概率。
也就是說,比如說樣例輸入吧,第一次n=1,最後落腳到0號點;第二次n=2,最後落腳到1號點,那麼第二次落腳到1號點的概率就等於第一次n=1落腳到0號點的概率乘上n=2落腳到1號點的概率。
以此類推,第三次n=3,落腳到0號點的概率等於前兩次的概率乘積乘上n=3落腳0號點的概率。
環上有n個點,從0號點出發走遍其他點,一共有中可能的順序,也就是其他n-1個點的排列數。
但是在這中情況中,最後落腳點爲m的情況有,也就是另外n-2個點的排列數
1.如果,從0號點出發,最後落腳點爲的概率爲
2.如果,從0號點出發,最後落腳點爲0號點,那麼概率一定爲0,因爲最後落腳點肯定不是0號點
3.如果,從0號點出發,最後落腳點爲0號點,概率一定爲1,因爲只有一個點,最後落腳點肯定是0號點
由於要按照所有場景發生的順序來輸出每個場景發生的概率,所以可以用一個前綴乘積來保存之前所有場景發生的概率,在乘上當前場景的概率,就是當前場景按順序發生的概率了。
注意還要分數取模用快速冪
舉個例子:
輸入:
3
4 2
3 1
2 0
首先第一個場景一共4個點,落腳2號點的概率爲,所以此場景按順序發生的概率爲
第二個場景一共3個點,落腳1號點的概率爲,所以此場景按順序發生的概率爲
第三個場景一共2個點,落腳0號點的概率爲,所以此場景按順序發生的概率爲
所以輸出
代碼如下:
#include <iostream>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int t,n,m;
ll ans=1;
ll qpow(ll x){//快速冪求分數取模逆元
ll pow=mod-2,sum=1;
while(pow){
if(pow%2==1) sum=sum*x%mod;
pow>>=1;
x=x*x%mod;
}
return sum;
}
int main(){
cin>>t;
while(t--){
scanf("%d%d",&n,&m);
//下面就是三種情況,注意ans保存前綴乘積
if(n==1 && m==0) ans=ans*1;
else if(m==0) ans=0;
else ans=ans*qpow(n-1)%mod;
printf("%lld\n",ans);
}
return 0;
}