• Noi2017 泳池


    首先考虑dp。

    不难发现我们大概是对于每一个高度不能有连续的一段长度,并且在下面都安全的时候才计入限制。

    (f[i][j])表示长度为i的泳池从高度j开始(i,j)的矩形默认安全,满足最大矩形小于k的概率.

    转移相当于做一个类似背包的东西。

    然后发现(j>0)的时候(ile 1000)(否则dp值为0),然后因为要枚举上一层选择了多少,这个最多到1000。

    则,枚举上一个0的位置

    [f[i][0]=sum f[j][0] * (f[i-j-1][1] * p^{i-j-1}*(1-p)) ]

    线性递推就没了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
    inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
    inline int mul(int a,int b){return (ll)a*b%mod;}
    inline int qpow(int a,int b)
        {int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
    inline int _inv(int x){return qpow(x,mod-2);}
    /* math */
    
    int n,k,x,y,p;
    const int N=1e3+6;
    int f[N][N];
    typedef vector<int> poly;
    poly F,A,R;
    
    poly mul(poly a,poly b){
        poly ret(a.size()+b.size()-1,0);
        for(size_t i=0;i<a.size();i++)for(size_t j=0;j<b.size();j++)ret[i+j]=add(ret[i+j],mul(a[i],b[j]));
        return ret;
    }
    poly Div(poly a,poly b){
        int t=b[b.size()-1];
        t=_inv(t);
        for(size_t i=a.size()-1;i>=b.size()-1;i--){
            int temp=mul(a[i],t);
            for(size_t pos=i,j=b.size()-1;~j;pos--,j--){
                a[pos]=sub(a[pos],mul(temp,b[j]));
            }
        }
        a.resize(min(a.size(),b.size()-1));
        return a;
    }
    
    inline int solve(int k){
        memset(f,0,sizeof(f));
        for(int j=0;j<=k+2;j++)f[0][j]=1;
        for(int i=1;i<=k;i++)for(int j=k/i;~j;j--){
            f[i][j]=mul(qpow(p,i),f[i][j+1]);
            for(int k=1,P=sub(1,p);k<=i;k++,P=mul(P,p)){
                f[i][j]=add(mul(f[k-1][j+1],mul(P,f[i-k][j])),f[i][j]);
            }
        }
        F.resize(k+2);
        for(int i=0;i<=k;i++)F[i]=mul(mul(sub(p,1),qpow(p,k-i)),f[k-i][1]);
        F[k+1]=1;
        A=poly(2,0);A[1]=1;
        R=poly(1,1);
        int K=n;
        for(;K;K>>=1){
            if(K&1){
                R=mul(R,A);
                R=Div(R,F);
            }
            A=mul(A,A);
            A=Div(A,F);
        }
        int ret=0;
        for(size_t i=0;i<R.size();i++){
            ret=add(ret,mul(R[i],f[i][0]));
        }
        return ret;
    }
    
    int main()
    {
        cin >> n >> k >> x >> y;p=mul(x,_inv(y));
        printf("%d
    ",sub(solve(k),solve(k-1)));
    }
    
    
  • 相关阅读:
    Python—格式化输出
    拨开Python迷雾
    彻底搞懂Python切片操作
    CodeMirror教程,CodeMirrorAPI中文信息
    PHP header() session_start() 函数前为什么不能有输出?
    PHP time() date() strtotime()日期函数总结
    LAMP专业术语的规范书写格式
    经验之谈
    PHP接口对方(C#)接收不到数据?ContentLength=1
    jQuery判断checkbox是否选中?操作checkbox(不)选中?
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/10961484.html
Copyright © 2020-2023  润新知