[期望概率]2016多校联合7 Knights

我是看这个懂的

思路:因为最后一个骑士肯定是往左走击败之前剩余的所有骑士,

所以只要考虑前面i−1个格子之后向右的骑士有j个的概率,考虑dp

(其实时间这个概念在这里不重要,因为如果前面有一个向左的骑士,那么如果它不变成向右走(变成向右走当且仅当它把之前向右走的杀完,活着的只剩它一个,此时特判),那么它一定不会死在与i的战斗里,它只会对向右的个数产生影响,然后死在i与向右走的骑士战斗之前,所以在考虑与第i个搏杀中,只需考虑前i个位置经过数轮搏杀(前i个位置中向左与向右的搏杀)最后有j个往右走的情况)

f[i][j]代表前i个位置经过数轮搏杀(前i个位置中向左与向右的搏杀)最后有j个往右走

#include <assert.h> //设定插入点
#include <ctype.h>   //字符处理
#include <errno.h>     //定义错误码
#include <float.h>     //浮点数处理
#include <limits.h>    //定义各种数据类型最值常量
#include <locale.h>    //定义本地化函数
#include <math.h>     //定义数学函数
#include <stdio.h>     //定义输入/输出函数
#include <stdlib.h>    //定义杂项函数及内存分配函数#include <string.h>    //字符串处理
#include <time.h>     //定义关于时间的函数#include <wchar.h>     //宽字符处理及输入/输出
#include<iostream>
#include <string.h>
#include <stdio.h>
#include <memory.h>
using namespace std;
typedef long long ll;
const long long mod=1e9+7;
long long T,n,o,t,a[10000],f[1010][1010];
ll pm(ll a, ll k){
    ll res = 1;
    while(k){
        if(k&1) res = (res*a)%mod;
        a = (a*a)%mod;
        k >>= 1;
    }
    return res;
}
int main()
{
  cin>>T; o=pm(2,mod-2); 
  while (T--)
  {
      cin>>n; 
     //  cout<<o<<endl;
      for (int i=1;i<=n;i++)  cin>>a[i];
      memset(f,0,sizeof(f));
      f[1][1]=1;
      for (int i=2;i<=n;i++)
    { 
      if (a[i]==1 && i!=n) 
      {for (int j=1;j<=i;j++) f[i][j]=f[i-1][j-1];}
        else 
       {for (int j=i;j>=2;j--)
         f[i][j]=(f[i][j+1]*o+f[i-1][j]*o)%mod;
         f[i][1]=(f[i][2]+f[i-1][1])%mod;
       }}
       cout<<"Case #"<<++t<<": "<<f[n][1]*o%mod<<endl;
    }

猜你喜欢

转载自blog.csdn.net/zzrh2018/article/details/81735593