传送门: Hdu 5819 Knights
题意:给你n个骑士,n+1个格子,刚开始第i个骑士站在第i个格子上,然后每个骑士都有一个初始的方向(向左或者向右,碰到格子的终点会反向),然后两个骑士相遇会进行决斗,每个骑士胜利的概率都是1/2,问最后剩下第n个骑士的概率
思路:因为最后一个骑士肯定是往左走击败之前剩余的所有骑士 ,
所以只要考虑前面i−1个格子之后向右的骑士有j个的概率,考虑dp
设dp[i][j]表示前面i个格子之后剩下j个骑士向右的概率,现在求解dp[i][j]
对第i个格子的方向进行分类讨论
1.假设第i个格子向左,那么dp[i][j]=∑i−1k=jdp[i−1][k]∗12k−j+1
而dp[i][j+1]=∑i−1k=j+1dp[i−1][k]∗12k−j
所以dp[i][j+1]=2∗dp[i][j]−dp[i−1][j]
2.当第i个格子向右,dp[i][j]=dp[i−1][j−1]
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
long long inv[1010],dp[1010][1010];
int a[1010];
int main(){
int _,n,m;
//freopen("1011.in","r",stdin);
inv[0]=0,inv[1]=1;
for(int i=2;i<=1001;i++)
inv[i]=inv[i-1]*500000004%MOD;
scanf("%d",&_);
for(int case1=1;case1<=_;case1++){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
dp[1][1]=1;
int cnt=1;
for(int i=2;i<n;i++){
if(a[i]==0){
dp[i][1]=0;
for(int j=1;j<=i-1;j++)
dp[i][1]=(dp[i][1]+dp[i-1][j]*inv[j])%MOD;
dp[i][2]=(dp[i][1]-dp[i-1][1])%MOD;
for(int j=3;j<i&&j<=cnt;j++)
dp[i][j]=(2*dp[i][j-1]-dp[i-1][j-1])%MOD;
}
else{
for(int j=2;j<=i;j++)
dp[i][j]=dp[i-1][j-1];
cnt++;
}
}
long long ans=0;
for(int i=1;i<=n-1;i++)
ans=(ans+dp[n-1][i]*inv[i+1])%MOD;
printf("Case #%d: %lld\n",case1,(ans+MOD)%MOD);
}
return 0;
}