[概率DP][多项式取模] NOI2017.day1 T3 泳池

标签: 多项式 DP
1263人阅读 评论(0) 收藏 举报
分类:

f(i,j)表示高度为i,长度为j的局域,i这个行存在障碍,前i-1行不存在障碍,能选取的区域<=k的概率

那么fi,j=k<jfi,kpi1qgi,jk1+k<jgi,kgi,jk1pi1q
其中p为一个格子安全的概率,q,为一个格子危险的概率。
gi,j表示i行,长度为j的区域不存在障碍,能选去的区域<=k的概率
那么gi,j=s>ifs,k

这样转移一下就可以了
可以按段转移,设h(i)为长度为i的答案
那么h(i)=j=1kh(ij)g(1,j)
这是一个线性递推式,用多项式取模可以完成。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>

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;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]);
  for(int i=1;i<n;i<<=1)
    for(int j=0;j<n;j+=i<<1)
      for(int k=0;k<i;k++){
    int 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);i<n;i++) a[i]=1LL*a[i]*iv%P;
}

inline void Pre(int n,int l){
  for(int i=1;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<l);
  int g=Pow(3,(P-1)/n),ig=inv(g); w[0][0]=w[1][0]=1;
  for(int i=1;i<n;i++)
    w[0][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;i<M;i++) a[i]=1LL*a[i]*a[i]%P;
    NTT(a,M,0);
    return ;
  }
  NTT(a,M,1); NTT(b,M,1);
  for(int i=0;i<M;i++) a[i]=1LL*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;i<n;i++) tmp[i]=a[i];
  for(int i=n;i<n<<1;i++) tmp[i]=0;
  NTT(tmp,n<<1,1); NTT(b,n<<1,1);
  for(int i=0;i<n<<1;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;i<n;i++) b[i]=tmp[i];
  for(int i=n;i<n<<1;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;i<n;i++) A[i]=a[n-i-1];
  int nn=1,d=n-m+1; for(;nn<d<<1;nn<<=1);
  for(int i=n;i<nn;i++) A[i]=0;
  for(int i=d;i<nn;i++) t[i]=0;
  for(int i=0;i<nn;i++) B[i]=0;
  Inv(t,B,nn);
  for(int i=d;i<nn;i++) B[i]=0;
  Mul(A,B,max(n,d));
  for(int i=d;i<=n<<1;i++) A[i]=0;
  for(int i=0;i<d;i++) if(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<n;i++) a[i]=(a[i]+P-t[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;
}
查看评论

【BZOJ4944】【NOI2017】泳池 概率DP 常系数线性递推 特征多项式 多项式取模

题目大意   有一个1001×n1001×n1001\times n的的网格,每个格子有qqq的概率是安全的,1−q1−q1-q的概率是危险的。   定义一个矩形是合法的当且仅当: ...
  • ez_yww
  • ez_yww
  • 2017-11-30 18:51:38
  • 766

NOI2017 最后的失败

前言      ~~~~~~CD类名单出了以后,机房的常驻人口就只有 9 个了。我们带着“中山纪念中学”这个荣誉称号,来到 NOI。       ~~~~~~然而这次普遍大翻车,没人进队。     ...
  • rzO_KQP_Orz
  • rzO_KQP_Orz
  • 2017-07-23 21:04:07
  • 3584

bzoj4944: [Noi2017]泳池【概率dp+特征多项式】

题目大意: 有一个1001×n1001×n1001×n的的网格,每个格子有qqq的概率是安全的,1−q1−q1−q的概率是危险的。 定义一个矩形是合法的当且仅当: 1.这个矩形中每个格子都是安全...
  • cdsszjj
  • cdsszjj
  • 2018-04-09 20:05:48
  • 37

【NOI2017】退役记——这是最坏的时代,也是最好的时代

NOI2017Day 0早上从重庆坐火车去杭州,中途在利川恩施段遇到暴雨铁路封闭,到杭州的时候比预计晚了大概80min,成功错过去绍兴的高铁,只好在杭州住了一晚上。Day1 Check in Day ...
  • outer_form
  • outer_form
  • 2017-07-29 00:08:09
  • 3344

noi2017解题报告(部分)

D1T1: 每30位压成一个int,然后压位线段树就可以过了。#include #define gc getchar() #define N 4500009 #define mid (l+r>>1...
  • wzf_2000
  • wzf_2000
  • 2017-08-07 09:28:39
  • 1242

ATP的NOI2017退役记

NOI滚粗,OI再见
  • FromATP
  • FromATP
  • 2017-07-22 09:27:45
  • 1290

[BZOJ4944][NOI2017]泳池-概率与期望-常系数线性递推-多项式取模

泳池 久莲是个爱玩的女孩子。 暑假终于到了,久莲决定请她的朋友们来游泳,她打算先在她家的私人海滩外圈一块长方形的海域作为游泳场。然而大海里有着各种各样的危险,有些地方水太深,有些地方有带毒的水母出...
  • zlttttt
  • zlttttt
  • 2018-02-19 17:09:17
  • 168

[概率DP][多项式取模] NOI2017.day1 T3 泳池

f(i,j)表示高度为i,长度为j的局域,i这个行存在障碍,前i-1行不存在障碍,能选取的区域&amp;lt;=k的概率 那么fi,j=∑k&amp;lt;jfi,k∗pi−1∗q∗gi,j−k−1...
  • Coldef
  • Coldef
  • 2017-07-24 15:03:50
  • 1263

多项式取模与线性递推优化

最近51nod比赛最后一题,我列出母函数以后发现要求m
  • lych_cys
  • lych_cys
  • 2016-11-04 20:03:11
  • 1757

FFT多项式快速幂,对于x^num取模,顺便再模一个998244353

多项式快速幂 时间限制 : 60000 MS 空间限制 : 524288 KB问题描述:给一个n次多项式,求它的k次方。没关系,随手模一个998244353就行了。没关系,再随手模一个xm就行了...
  • INCINCIBLE
  • INCINCIBLE
  • 2017-02-05 22:11:09
  • 874
    个人资料
    持之以恒
    等级:
    访问量: 10万+
    积分: 5255
    排名: 6493
    文章分类
    最新评论