$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 }