• 【2019北京集训测试赛(七)】 操作 分治+FFT+生成函数


    题目大意:你有$n$个操作和一个初始为$0$的变量$x$。

    第$i$个操作为:以$P_i$的概率给$x$加上$A_i$,剩下$1-P_i$的概率给$x$乘上$B_i$。

    你袭击生成了一个长度为$n$的排列$C$,并以此执行了第$C_1,C_2....C_n$个操作。

    求执行完所有操作后,变量$x$的期望膜$998244353$的值。

    数据范围:$n≤10^5,0≤P,A,B<998244353$

    我太菜了

    考虑如果并没有排列的要求,而是强行依次执行,会发生什么事情:

    令$X_i$表示执行完前$i$个操作后$x$的期望。

    则有:

    $X_i=P_i imes (X_{i-1}+A_i)+(1-P_i) imes X_{i-1} imes B_i$

    我们经过化简,得到:

    $X_i=(P_i+B_i-P_i imes B_i)X_{i-1}+A_i imes B_i$

    这个不就是一个一次函数吗?我们姑且将这个称为$F_i(x)$,我们将它表示为$F_i(x)=D_ix+E_i$

    那么在不考虑顺序的情况下,则有:

    $X_n=F_1(F_2(...F_n(0)...))$

    然而求答案的时候,函数排列的顺序是随机的,对于任意的$i≠j$,函数i排在函数j前面的概率都是$frac{1}{2}$。

    我们只需要求出,对于每个$E_i$,套在$F_i(x)$外面的函数的积的期望。

    基于这些,则有:

    $X_n=frac{1}{n!}sum limits_{i=1}^{n} E_i sum limits_{j=1}^{n} [x^j] prod limits_{k=1,k otequiv i}^{n}(1+D_k)$

    然后,我们通过分治FFT求解这个式子即可。

     1 #include<bits/stdc++.h>
     2 #define MOD 998244353
     3 #define G 3
     4 #define L long long
     5 #define M 262144
     6 using namespace std;
     7 
     8 L pow_mod(L x,L k){L ans=1; for(;k;k>>=1,x=x*x%MOD) if(k&1) ans=ans*x%MOD; return ans;}
     9 void chage(int a[],int n){
    10     for(int i=0,j=0;i<n-1;i++){
    11         if(i<j) swap(a[i],a[j]);
    12         int k=n>>1;
    13         while(j>=k) j-=k,k>>=1;
    14         j+=k;
    15     }
    16 }
    17 inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:a+b;}
    18 inline int mns(int a,int b){return a<b?a-b+MOD:a-b;}
    19 void NTT(int a[],int n,int on){
    20     chage(a,n);
    21     for(int h=2;h<=n;h<<=1){
    22         int wn=pow_mod(G,(MOD-1)/h);
    23         for(int j=0;j<n;j+=h){
    24             int w=1;
    25             for(int k=j;k<j+(h>>1);k++){
    26                 int u=a[k],t=1LL*a[k+(h>>1)]*w%MOD;
    27                 //a[k]=(u+t)%MOD; a[k+(h>>1)]=(u-t+MOD)%MOD;
    28                 a[k]=pls(u,t); a[k+(h>>1)]=mns(u,t);
    29                 w=1LL*w*wn%MOD;
    30             }
    31         }
    32     }
    33     if(on==-1){
    34         L inv=pow_mod(n,MOD-2);
    35         reverse(a+1,a+n);
    36         for(int i=0;i<n;i++) a[i]=1LL*a[i]*inv%MOD;
    37     }
    38 }
    39 void MUL(int ans[],int a[],int lena,int b[],int lenb){
    40     static int t1[M],t2[M];
    41     int len=1; while(len<=lena+lenb) len<<=1;
    42     memset(t1,0,len<<2); memcpy(t1,a,(lena+1)<<2);
    43     memset(t2,0,len<<2); memcpy(t2,b,(lenb+1)<<2);
    44     NTT(t1,len,1); NTT(t2,len,1);
    45     for(int i=0;i<len;i++) t1[i]=1LL*t1[i]*t2[i]%MOD;
    46     NTT(t1,len,-1);
    47     memcpy(ans,t1,(lena+lenb+1)<<2);
    48 }
    49 
    50 L D[M]={0},E[M]={0},fac[M]={0};
    51 void solve(int f[],int g[],int l,int r){
    52     static int h[M];
    53     if(l==r) return f[0]=E[l],g[1]=D[l],g[0]=1,void();
    54     int mid=(l+r)>>1,lenl=mid-l+1,lenr=r-mid;
    55     solve(f,g,l,mid); solve(f+lenl+2,g+lenl+2,mid+1,r);
    56     MUL(h,f,lenl-1,g+lenl+2,lenr);
    57     MUL(f,f+lenl+2,lenr-1,g,lenl);
    58     for(int i=0;i<=r-l+1;i++) f[i]=(f[i]+h[i])%MOD;
    59     MUL(g,g,lenl,g+lenl+2,lenr);
    60 }
    61 
    62 int ff[M]={0},gg[M]={0};
    63 int main(){
    64     fac[0]=1; for(int i=1;i<M;i++) fac[i]=fac[i-1]*i%MOD;
    65     int n; scanf("%d",&n);
    66     for(int i=1;i<=n;i++){
    67         L P,B,A; scanf("%lld%lld%lld",&P,&A,&B);
    68         D[i]=(P+B-P*B%MOD+MOD)%MOD;
    69         E[i]=A*P%MOD;
    70     }
    71     solve(ff,gg,1,n);
    72     L ans=0;
    73     for(int i=0;i<n;i++) (ans+=1LL*ff[i]*fac[i]%MOD*fac[n-i-1])%=MOD;
    74     ans=ans*pow_mod(fac[n],MOD-2)%MOD;
    75     cout<<ans<<endl;
    76 }

     

  • 相关阅读:
    luogu P1955 [NOI2015]程序自动分析
    luogu P5514 [MtOI2019]永夜的报应
    bzoj1816[Cqoi2010]扑克牌
    bzoj1040[ZJOI2008]骑士
    bzoj4582[Usaco2016 Open]Diamond Collector
    bzoj1029[JSOI2007]建筑抢修
    bzoj1079[SCOI2008]着色方案
    bzoj1051[HAOI2006]受欢迎的牛
    bzoj4525[Usaco2016 Jan]Angry Cows
    bzoj4512[Usaco2016 Jan] Build Gates
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10694236.html
Copyright © 2020-2023  润新知