Problem:
Problem C: カードゲーム

ねこのゲイツとジャッキーは、2人で遊ぶカードゲームのルールを考えた。そのルールとは次のようなものである。

まず、1から18の数字が書かれたカードをシャッフルし、それぞれのプレーヤーに9枚ずつ配る。両者は同時に1枚のカードを同時に出し、その値によってスコアを得る。値の大きいカードを出したプレーヤーは、大きい方の値と小さい方の値の和を自分のスコアに加える。その際、値の小さいカードを出したプレーヤーはスコアを得られない。また、一度場に出されたカードは二度と使うことはできない。カードをすべて使い終わった後にスコアが大きかったプレーヤーの勝ちとする。

ゲイツとジャッキーは互いに無作為にカードを選んで出してみることにした。最初に配られたカードが与えられたとき、ゲイツとジャッキーが勝つ確率をそれぞれ求めよ。

Input

ゲイツ、ジャッキーそれぞれの手札は、9個の整数からなる。両プレーヤーの手札は1から18までの互いに異なる整数である。入力の1行目にはゲイツの手札を表す9個の整数が与えられ、2行目にはジャッキーの手札を表す9個の整数が与えられる。整数と整数の間は空白1個で区切られる。

Output

ゲイツ、ジャッキーが勝つ確率をそれぞれ、スペースで区切って小数点以下5桁まで出力せよ。 10-5 以内の誤差は許容されるが、0未満あるいは1を越える値を出力してはならない。

Notes on Submission

上記形式で複数のデータセットが与えられます。入力データの 1 行目にデータセットの数が与えられます。各データセットに対する出力を上記形式で順番に出力するプログラムを作成して下さい。

Sample Input

2
1 3 5 7 9 11 13 15 17
2 4 6 8 10 12 14 16 18
1 5 7 9 11 13 15 17 18
2 3 4 6 8 10 12 14 16

Output for the Sample Input

0.30891 0.69109
0.92747 0.07253

Solution in C++ (judge verdict: Accepted)

#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
typedef long long int ll;

#define BIG_NUM 2000000000

using namespace std;

int table_4[24][4],table_5[120][5],index_9,m_data[9] = {0,1,2,3,4,5,6,7,8};
int** table_9;

void calc9(){
	int select_num = 5,num,loc_left[5],loc_right[4],left_index,right_index,left_calc[5],right_calc[4];

	index_9 = 0;

	for(int i = 0; i < 512;i++){
		num = 0;
		for(int k = 0; k < 9; k++){
			if(i & (1 << k))num++;
		}
		if(num != select_num)continue;

		left_index = right_index = 0;

		for(int k = 0; k < 9; k++){
			if(i & (1 << k)){
				loc_left[left_index++] = k;
			}else{
				loc_right[right_index++] = k;
			}
		}

		left_index = right_index = 0;

		left_calc[0] = m_data[loc_left[0]],left_calc[1] = m_data[loc_left[1]],left_calc[2] = m_data[loc_left[2]],left_calc[3] = m_data[loc_left[3]],left_calc[4] = m_data[loc_left[4]];
		right_calc[0] = m_data[loc_right[0]],right_calc[1] = m_data[loc_right[1]],right_calc[2] = m_data[loc_right[2]],right_calc[3] = m_data[loc_right[3]];

		for(int k = 0; k < 120; k++){
			for(int p = 0; p < 24; p++){
				for(int a = 0; a < 4; a++){
					table_9[index_9][a] = left_calc[table_5[k][a]];
					table_9[index_9][5+a] = right_calc[table_4[p][a]];
				}
				table_9[index_9][4] = left_calc[table_5[k][4]];
				index_9++;
			}
		}
	}
}


int main(){

	int index_4 = 0;

	for(int a = 0; a < 4; a++){
		for(int b = 0; b < 4; b++){
			for(int c = 0; c < 4; c++){
				for(int d = 0; d < 4; d++){
					if(a != b && a != c && a != d && b != c && b != d && c != d){
						table_4[index_4][0] = a,table_4[index_4][1] = b,table_4[index_4][2] = c,table_4[index_4][3] = d;
						index_4++;
					}
				}
			}
		}
	}

	int index_5 = 0;

	for(int a = 0; a < 5; a++){
		for(int b = 0; b < 5; b++){
			for(int c = 0; c < 5; c++){
				for(int d = 0; d < 5; d++){
					for(int e = 0; e < 5; e++){
						if(a != b && a != c && a != d && a != e && b != c && b != d && b != e && c != d && c != e && d != e){
							table_5[index_5][0] = a,table_5[index_5][1] = b,table_5[index_5][2] = c,table_5[index_5][3] = d,table_5[index_5][4] = e;
							index_5++;
						}
					}
				}
			}
		}
	}



	table_9 = new int*[362880];
	for(int i = 0; i < 362880; i++){
		table_9[i] = new int[9];
	}

	calc9();

	int K,gates[9],jenny[9],count,score_G,score_J,work[9];
	double ans_J,ans_G;
	scanf("%d",&K);

	for(int loop = 0; loop < K; loop++){
		for(int i = 0; i < 9; i++)scanf("%d",&gates[i]);
		for(int i = 0; i < 9; i++)scanf("%d",&jenny[i]);

		count = 0;
		for(int i = 0; i < 362880; i++){
			score_G = 0,score_J = 0;
			for(int k = 0; k < 9; k++){
				work[k] = jenny[table_9[i][k]];

				if(work[k] > gates[k]){
					score_J += work[k] + gates[k];
				}else{
					score_G += gates[k] + work[k];
				}
			}
			if(score_J > score_G)count++;
		}

		ans_J = (double)count/(double)362880;
		ans_G = 1 - ans_J;

		printf("%.5lf %.5lf\n",ans_G,ans_J);
	}

    return 0;
}