zoukankan      html  css  js  c++  java
  • [期望DP]「BJOI2018」治疗之雨

    解题思路

    (g[i])表示(k)次攻击后掉(i)滴血的概率,显然有(g[i]=C_{k}^{i}(frac{1}{m+1})^i(frac{m}{m+1})^{k-i})

    (f[i])表示英雄初始血量为(i)的期望存活轮数,那么显然有:

    [f[i]=sum_{j=0}^{min(i+1,k)}(frac{1}{m+1})g[j]f[i+1-j]+sum_{j=0}^{j=min(i,k)}(frac{m}{m+1})g[j]f[i-j]+1 ]

    血量为(n)时不能加血,所以转移有所不同:

    [f[n]=sum_{j=0}^{j=min(n,k)}g[j]f[n-j]+1 ]

    通过上面的第一个式子可以将(f[i])推到(f[i+1]),然后发现一个很大的问题(f[1])并不确定

    所以我们将(f[1])设为(X),那么(f)的每个状态都类似(aX+b)的形式,然后跟第二个式子解出(X)的值即可.

    #include<cstdio>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int maxn=1505,tt=1e9+7;
    struct jz{
    	int x,y;
    	jz(int x=0,int y=0):x(x),y(y){}
    	jz operator+(const jz &b)const{return jz((x+b.x)%tt,(y+b.y)%tt);}
    	jz operator-(const jz &b)const{return jz((x-b.x+tt)%tt,(y-b.y+tt)%tt);}
    	jz operator*(int w)const{return jz((LL)x*w%tt,(LL)y*w%tt);}
    }f[maxn],ans;
    int g[maxn],n,p,m,k,T;
    int qsm(int w,int b){int num=1;while(b){if (b&1) num=(LL)num*w%tt;w=(LL)w*w%tt;b>>=1;}return num;}
    int work1(){
        if(k==1&&n!=1) return -1;
        g[0]=0;for(int i=1;i<n;i++) g[i]=g[max(i+1-k,0)]+1;
        g[n]=g[max(n-k,0)]+1;
        return g[p];
    }
    int work(){
    	scanf("%d%d%d%d",&n,&p,&m,&k);int Invm=qsm(m+1,tt-2);
    	if (!k) return -1;if (!m) return work1();
    	int C=1;for (int i=0;i<=min(k,n);i++) g[i]=(LL)C*qsm(Invm,i)%tt*qsm((LL)m*Invm%tt,k-i)%tt,C=(LL)C*(k-i)%tt*qsm(i+1,tt-2)%tt;
    	if (g[0]==1||g[0]==0) return -1;
    	f[0]=jz(0,0);f[1]=jz(1,0);
    	for (int i=1;i<n;i++){
    		f[i+1]=(f[i]-jz(0,1))*(m+1);
    		for (int j=0;j<=min(i,k);j++) f[i+1]=f[i+1]-(f[i-j]*g[j])*m;
    		for (int j=1;j<=min(i+1,k);j++) f[i+1]=f[i+1]-(f[i+1-j]*g[j]);
    		f[i+1]=f[i+1]*qsm(g[0],tt-2); 
    	}
    	ans=jz(0,1);for (int i=1;i<=min(n,k);i++) ans=ans+f[n-i]*g[i];
    	ans=ans*qsm(1-g[0]+tt,tt-2);ans=ans-f[n];
    	if (!ans.x&&f[p].x) return -1;int X=(LL)ans.y*qsm(tt-ans.x,tt-2)%tt;
    	return ((LL)f[p].x*X+f[p].y)%tt;
    }
    int main(){
    	freopen("exam.in","r",stdin);
    	freopen("exam.out","w",stdout);
    	scanf("%d",&T);while(T--) printf("%d
    ",work());return 0;
    } 
    
  • 相关阅读:
    MySQL与PostgreSQL对比
    Elastic Job3.0
    Nacos Config动态刷新值
    clickhouse数据类型
    字符串和整数之间的转换
    STL之优先队列 priority_queue
    c++智能指针
    springcloud gateway: discovery: locator: enabled: true 解释
    工具资源下载链接 webstorm
    技术链接汇总
  • 原文地址:https://www.cnblogs.com/CHNJZ/p/10560457.html
Copyright © 2011-2022 走看看