f(i,j)表示高度为i,长度为j的局域,i这个行存在障碍,前i-1行不存在障碍,能选取的区域<=k的概率
那么 fi,j=∑k<jfi,k∗pi−1∗q∗gi,j−k−1+∑k<jgi,k∗gi,j−k−1∗pi−1∗q f i , j = ∑ k < j f i , k ∗ p i − 1 ∗ q ∗ g i , j − k − 1 + ∑ k < j g i , k ∗ g i , j − k − 1 ∗ p i − 1 ∗ q ,
其中p为一个格子安全的概率,q,为一个格子危险的概率。
gi,j g i , j 表示i行,长度为j的区域不存在障碍,能选去的区域<=k的概率
那么 gi,j=∑s>ifs,k g i , j = ∑ s > i f s , k
这样转移一下就可以了
可以按段转移,设 h(i) h ( i ) 为长度为i的答案
那么 h(i)=∑kj=1h(i−j)∗g(1,j) h ( i ) = ∑ j = 1 k h ( i − j ) ∗ g ( 1 , j )
这是一个线性递推式,用多项式取模可以完成。
#include
#include
#include
#include
#include
using namespace std;
const int N=5100,P=998244353;
inline int Pow(int x,int y){
int ret=1;
for(;y;y>>=1,x=1LL*x*x%P) if(y&1) ret=1LL*ret*x%P;
return ret;
}
inline int inv(int x){
return Pow(x,P-2);
}
inline void add(int &x,int y){
(x+=y)%=P;
}
int n,k,x,y,p,q;
int f[N][N],g[N],pw[N],h[N],a[N],F[N],d[N];
int rev[N],w[2][N],num;
inline void NTT(int *a,int n,int r){
for(int i=1;iif(rev[i]>i) swap(a[i],a[rev[i]]);
for(int i=1;i1)
for(int j=0;j1)
for(int k=0;kint x=a[j+k],y=1LL*w[r][n/(i<<1)*k]*a[i+j+k]%P;
a[j+k]=(x+y)%P; a[i+j+k]=(x+P-y)%P;
}
if(!r) for(int i=0,iv=Pow(n,P-2);i1LL*a[i]*iv%P;
}
inline void Pre(int n,int l){
for(int i=1;i>1]>>1)|((i&1)<int g=Pow(3,(P-1)/n),ig=inv(g); w[0][0]=w[1][0]=1;
for(int i=1;i0][i]=1LL*w[0][i-1]*ig%P,w[1][i]=1LL*w[1][i-1]*g%P;
}
inline void Mul(int *a,int *b,int m){
int l=-1,M; for(M=1;M<(m<<1);M<<=1) l++; Pre(M,l);
if(a==b){
NTT(a,M,1);
for(int i=0;i1LL*a[i]*a[i]%P;
NTT(a,M,0);
return ;
}
NTT(a,M,1); NTT(b,M,1);
for(int i=0;i1LL*a[i]*b[i]%P;
NTT(a,M,0); NTT(b,M,0);
}
int tmp[N],A[N],B[N];
void Inv(int *a,int *b,int n){
if(n==1) return b[0]=inv(a[0]),void();
Inv(a,b,n+1>>1);
static int tmp[N];
int L=0; while(!(n>>L&1)) L++; Pre(n<<1,L);
for(int i=0;ifor(int i=n;i1;i++) tmp[i]=0;
NTT(tmp,n<<1,1); NTT(b,n<<1,1);
for(int i=0;i1;i++)
tmp[i]=(2LL*b[i]%P+P-1LL*tmp[i]*b[i]%P*b[i]%P)%P;
NTT(tmp,n<<1,0);
for(int i=0;ifor(int i=n;i1;i++) b[i]=0;
}
int t[N],bb[N];
inline void Div(int *a,int n,int *b,int m){
static int tmp[N],A[N],B[N];
for(int i=0;i<m;i++) t[i]=b[m-i-1];
for(int i=0;i1];
int nn=1,d=n-m+1; for(;nn1;nn<<=1);
for(int i=n;i0;
for(int i=d;i0;
for(int i=0;i0;
Inv(t,B,nn);
for(int i=d;i0;
Mul(A,B,max(n,d));
for(int i=d;i<=n<<1;i++) A[i]=0;
for(int i=0;iif(i>d-i-1) swap(A[i],A[d-i-1]);
for(int i=0;i<m;i++) t[i]=b[i];
Mul(t,A,max(d,m));
for(int i=0;i%P;
}
inline void mul(int *a,int *b,int m){
Mul(a,b,m);
Div(a,2*m,d,m+1);
}
inline void Pow(int *a,int m,int n,int *b){
for(;n;n>>=1,mul(a,a,m))
if(n&1) mul(b,a,m);
}
inline int solve(int m){
memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
f[m+1][1]=1LL*pw[m]*q%P; g[0]=1; g[1]=f[m+1][1];
for(int i=m;i;i--){
f[i][0]=1;
for(int j=1;(i-1)*j<=m && j<=m;j++)
for(int s=1;s<=j;s++){
if(s>1) add(f[i][j],1LL*f[i][s-1]*g[j-s]%P*pw[i-1]%P*q%P);
add(f[i][j],1LL*g[s-1]*g[j-s]%P*pw[i-1]%P*q%P);
}
if(i==1) memcpy(h,g,sizeof(h));
for(int j=1;(i-1)*j<=m && j<=m;j++)
add(g[j],f[i][j]);
}
if(n<=m) return g[n];
for(int i=m+1;i;i--)
h[i]=1LL*h[i-1]*q%P;
m++;
memset(a,0,sizeof(a)); memset(d,0,sizeof(d));
memset(F,0,sizeof(F));
for(int i=0;i<m;i++) d[i]=(P-h[m-i])%P;
d[m]=1; a[1]=1;
F[0]=1;
Pow(a,m,n,F);
int ret=0;
for(int i=0;i<m;i++) add(ret,1LL*F[i]*g[i]%P);
return ret;
}
int main(){
scanf("%d%d%d%d",&n,&k,&x,&y);
p=1LL*x*inv(y)%P; q=(1+P-p)%P; pw[0]=1;
for(int i=1;i<=k;i++) pw[i]=1LL*pw[i-1]*p%P;
printf("%d\n",(solve(k)+P-solve(k-1))%P);
return 0;
}