Noi2017 泳池

首先考虑dp。

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

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

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

然后发现\(j>0\)的时候\(i\le 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\n",sub(solve(k),solve(k-1)));
}
上一篇:斯特林数学习笔记


下一篇:洛谷 P2791 幼儿园篮球题