【2019北京集訓測試賽(七)】 操做 分治+FFT+生成函數

題目大意:你有$n$個操做和一個初始爲$0$的變量$x$。c++

第$i$個操做爲:以$P_i$的機率給$x$加上$A_i$,剩下$1-P_i$的機率給$x$乘上$B_i$。函數

你襲擊生成了一個長度爲$n$的排列$C$,並以此執行了第$C_1,C_2....C_n$個操做。ui

求執行完全部操做後,變量$x$的指望膜$998244353$的值。spa

數據範圍:$n≤10^5,0≤P,A,B<998244353$code

 

我太菜了blog

考慮若是並無排列的要求,而是強行依次執行,會發生什麼事情:it

令$X_i$表示執行完前$i$個操做後$x$的指望。class

則有:變量

$X_i=P_i\times (X_{i-1}+A_i)+(1-P_i)\times X_{i-1}\times B_i$im

咱們通過化簡,獲得:

$X_i=(P_i+B_i-P_i\times B_i)X_{i-1}+A_i\times 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\not\equiv 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 }
相關文章
相關標籤/搜索