1. 程式人生 > >一道題7

一道題7

span 個數 space 後序 mem iostream for 轉移 d+

$n \leq 40$個數字初始為0,$m \leq 10$次操作每次以給定概率$P(i,j,k)$選擇二元組$(j,k)$,表示第$j$個數加上$k$,$0 \leq k \leq C \leq 3$,$C$是給定常數。問最後序列的期望最大值。

狀壓太菜要補啊。

以數字為切入點,把每個數字分開計算最後合起來。但是註意新加進一個數的轉移不能單看這個數的值的概率,還要看操作。因此把操作表示進狀態。

$f(i,j,k)$--前$i$個數,操作集合$j$時,最大值$k$的概率。$g(i,j,k)$--第$i$個數,操作集合$j$時,值為$k$的概率。轉移略。

技術分享圖片
 1 #include<stdio.h>
 2
#include<string.h> 3 #include<stdlib.h> 4 //#include<queue> 5 //#include<vector> 6 #include<algorithm> 7 //#include<iostream> 8 //#include<assert.h> 9 using namespace std; 10 11 int n,m,c; 12 #define LL long long 13 LL f[2][1111][35],sf[1111][35],g[1111][35],sg[1111
][35]; int cur,p[11][44][5],sp[44]; 14 const int mod=1e9+7; 15 int main() 16 { 17 scanf("%d%d%d",&n,&m,&c); 18 for (int i=1;i<=n;i++) sp[i]=1; 19 for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) 20 { 21 int tot=0; 22 for (int k=0;k<=c;k++) 23 scanf("
%d",&p[i][j][k]),tot+=p[i][j][k],tot-=tot>=mod?mod:0; 24 sp[j]=1ll*sp[j]*(mod+1-tot)%mod; 25 } 26 27 cur=0; f[0][0][0]=1; int tot=m*c; 28 for (int i=1;i<=n;i++) 29 { 30 for (int j=0;j<(1<<m);j++) 31 { 32 sf[j][0]=f[cur][j][0]; 33 for (int k=1;k<=tot;k++) sf[j][k]=sf[j][k-1]+f[cur][j][k],sf[j][k]-=sf[j][k]>=mod?mod:0; 34 } 35 memset(g,0,sizeof(g)); g[0][0]=1; 36 for (int j=0;j<(1<<m);j++) 37 { 38 int tmp=0; 39 for (int k=1;k<=m;k++) if (((j>>(k-1))&1)==1) tmp=k; 40 for (int k=tmp+1;k<=m;k++) 41 { 42 int s=j|(1<<(k-1)); 43 for (int t=0,to=tot;t<=to;t++) 44 for (int l=0;l<=c;l++) 45 g[s][t+l]+=g[j][t]*1ll*p[k][i][l]%mod,g[s][t+l]-=g[s][t+l]>=mod?mod:0; 46 } 47 } 48 for (int j=0;j<(1<<m);j++) 49 { 50 sg[j][0]=g[j][0]; 51 for (int k=1;k<=tot;k++) sg[j][k]=sg[j][k-1]+g[j][k],sg[j][k]-=sg[j][k]>=mod?mod:0; 52 } 53 54 for (int j=0;j<(1<<m);j++) 55 { 56 int fj=(1<<m)-j-1; 57 for (int s=fj;;s=(s-1)&fj) 58 { 59 for (int k=1;k<=tot;k++) f[cur^1][j|s][k]+=f[cur][j][k]*1ll*sg[s][k-1]%mod, 60 f[cur^1][j|s][k]-=f[cur^1][j|s][k]>=mod?mod:0; 61 for (int k=0;k<=tot;k++) f[cur^1][j|s][k]+=sf[j][k]*1ll*g[s][k]%mod, 62 f[cur^1][j|s][k]-=f[cur^1][j|s][k]>=mod?mod:0; 63 if (s==0) break; 64 } 65 } 66 memset(f[cur],0,sizeof(f[cur])); 67 cur^=1; 68 } 69 70 int ans=0; 71 for (int j=1,tmp=(1<<m)-1;j<=tot;j++) ans+=f[cur][tmp][j]*1ll*j%mod,ans-=ans>=mod?mod:0; 72 printf("%d\n",ans); 73 return 0; 74 }
View Code

一道題7