こちらの方が易しく感じました。
http://yukicoder.me/problems/326
解法
BitDPを用いて、A君・B君のカードのうち、何番目に小さい番号のカードが何試合目に出されるかを求める。
そこから、A君のx番目のカードがB君のy番目のカードと当たる確率P[x][y]が求められる。
あとはA[x]>B[y]なカードA[x],B[y]に対し、(A[x]+B[y])*P[x][y]の総和を取ればよい。
int N,T; double P[2],ret; int A[30],B[30]; double PP[2][1<<21]; double PQ[2][21][21]; void solve() { int i,j,k,l,r,x,y; string s; cin>>N>>P[0]>>P[1]; FOR(i,N) cin>>A[i]; FOR(i,N) cin>>B[i]; sort(A,A+N); sort(B,B+N); PP[0][0]=PP[1][0]=1; FOR(i,N) FOR(x,1<<N) if(__builtin_popcount(x)==i) { int f=1; FOR(j,N) if((x & (1<<j))==0) { if(i==N-1) { PP[0][x | (1<<j)] += PP[0][x]; PP[1][x | (1<<j)] += PP[1][x]; PQ[0][j][i] += PP[0][x]; PQ[1][j][i] += PP[1][x]; } else { if(f) { PP[0][x | (1<<j)] += PP[0][x] * P[0]; PP[1][x | (1<<j)] += PP[1][x] * P[1]; PQ[0][j][i] += PP[0][x] * P[0]; PQ[1][j][i] += PP[1][x] * P[1]; f=0; } else { PP[0][x | (1<<j)] += PP[0][x] * (1-P[0])/(N-1-i); PP[1][x | (1<<j)] += PP[1][x] * (1-P[1])/(N-1-i); PQ[0][j][i] += PP[0][x] * (1-P[0])/(N-1-i); PQ[1][j][i] += PP[1][x] * (1-P[1])/(N-1-i); } } } } FOR(i,N) FOR(x,N) FOR(y,N) if(A[x]>B[y]) ret += (A[x]+B[y]) * PQ[0][x][i]*PQ[1][y][i]; _P("%.12lf\n",ret); }
まとめ
1月2月の好調に反し、3月はイマイチ不調なので4月から盛り返したい。