Problem:
問題名 Audition
アイドル---それは女の子達の永遠の憧れ。しかし、頂点に立てるのはほんの一握り。そんなサバイバルな世界に、あなたはアイドルプロデューサーとして足を踏み入れることになりました。そして、今日はあなたの担当アイドルを連れて大事なオーディションに挑むことになりました。
オーディションの決め手になるのはビジュアル、ダンス、ボーカルの 3 要素です。オーディション中には
m
回のアピールタイムがあり、 1 回のアピールタイムごとに各アイドルはビジュアルアピール、ダンスアピール、ボーカルアピールのいずれかを行うことが出来ます。ビジュアルアピールを行うとそのアイドルのビジュアルポイントは彼女の持ってるビジュアル値だけ、ダンスアピールを行うとダンスポイントは彼女の持ってるダンス値だけ、ボーカルアピールを行うとボーカルポイントは彼女の持ってるボーカル値だけ上昇します。
m
回のアピールが終了した後、
N
人のアイドルのうちビジュアルポイントの高いほうから 3 人は 5 オーディションポイント、ダンスポイントの高いほうから 3 人は 3 オーディションポイント、ボーカルポイントの高いほうから 3 人は 2 オーディションポイントを獲得します。一方、ビジュアルポイントが最下位だとオーディションポイントは 1 点減点、ダンスポイントが最下位だとオーディションポイントは 1 点減点、ボーカルポイントが最下位だとオーディションポイントは 1 点減点となります。（オーディションポイントが1以下でもそこから 1 点減点）。
オーディションの始めに、各アイドルのビジュアルポイント、ダンスポイント、ボーカルポイントはそれぞれ 0 です。あなたはアイドル 1 のプロデューサーで、アピールタイムごとにどのアピールを行うか指示することが出来ます。アイドル 1 以外のアイドルはアピールタイムごとにランダムに等確率にどれかのアピールを行います（つまりそれぞれ 3 分の 1 の確率で行われる）。アイドル 1 のビジュアル、ダンス、ボーカルのポイントが他のアイドルと等しい場合、アイドル 1 は常に下位とします。アイドル 1 の獲得するオーディションポイントの期待値が最大になるように指示したときの期待値を求めて下さい。アイドルの運命は、あなたの指示にかかっています！
ちなみに、指示はオーディションが始まる前に全て行って、その後オーディション中の指示の変更は出来ないものとします。つまり、他のアイドルが、オーディションが始まってからのアピールでどのアピールをしかたを見てから、その場合においての期待値が最大となるような指示を出す、ということは出来ないものとします。
Input
入力は以下の形で与えられます。
n
m
vi
1
da
1
vo
1
vi
2
da
2
vo
2
...
vi
n
da
n
vo
n
1行目にはオーディションに出場するアイドルの数
n
(
4 ≤ n ≤ 2000
) と、このオーディションにおけるアピールタイムの数
m
(
1 ≤ m ≤ 2000
) が書いてあります。次の
n
行にはそれぞれアイドルiのビジュアル値
vi
i
、ダンス値
da
i
、ボーカル値
vo
i
(
1 ≤ vi
i
, da
i
, vo
i
≤ 10,000
)が書いてあります。
Output
アイドル 1 の獲得するオーディションポイントの期待値の最大値を 1 行で出力しなさい。
Sample Input 1
4 1
1 1 1
1 1 1
1 1 1
1 1 1
Output for the Sample Input 1
2.777777777778
どのアピールを行っても、そのジャンルで 3 位以内に入れる確率は等しいですが、 3 位以内に入った時に貰えるオーディションポイントが最も多いビジュアルのアピールを行うのがもっとも期待値が良くなります。
Sample Input 2
4 10
1 1 1
10 10 10
10 10 10
10 10 10
Output for the Sample Input 2
-2.335340954780
非常に厳しいオーディションとなるでしょう。
Sample Input 3
9 9
13 5 19
19 21 37
15 1 7
7 11 15
21 23 25
33 29 19
13 19 11
21 5 15
7 13 1
Output for the Sample Input 3
4.678837855075

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rrep(i, a, b) for (ll i = (ll)(b)-1; i >= (ll)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

vector<double> P;

vector<double> Solve(int N, int M, int K, int X, vector<int> A) {
    vector<double> Ret(M+1,0.0);
    rep(i,0,M+1) {
        vector<double> DP(3,0.0);
        DP[0] = 1.0;
        double ALLLose = 1.0;
        rep(j,0,N) {
            int LoseNum = ceil(X*i,A[j]);
            double Lose;
            if (LoseNum >= M+1) Lose = 0.0;
            else if (LoseNum < 0) Lose = 1.0;
            else Lose = P[LoseNum];
            double Win = 1.0 - Lose;
            ALLLose *= Lose;
            vector<double> NewDP(3,0.0);
            rep(k,0,3) {
                NewDP[k] += DP[k] * Win;
            }
            rep(k,0,2) {
                NewDP[k+1] += DP[k] * Lose;
            }
            swap(DP,NewDP);
        }
        Ret[i] = (DP[0]+DP[1]+DP[2]) * (double)K - ALLLose;
    }
    return Ret;
}

int main() {
    int N, M;
    cin >> N >> M;
    N--;
    P.resize(M+1,0.0);
    P[0] = 1.0;
    rep(i,0,M) {
        vector<double> NP(M+1,0.0);
        rep(j,0,i+1) {
            NP[j] += P[j] * 2.0 / 3.0;
            NP[j+1] += P[j] / 3.0;
        }
        swap(P,NP);
    }
    rrep(i,0,M) P[i] += P[i+1];
    vector<int> X(3);
    vector<vector<int>> A(3,vector<int>(N));
    rep(i,0,3) cin >> X[i];
    rep(i,0,N) rep(j,0,3) cin >> A[j][i];
    vector<vector<double>> D = {Solve(N,M,5,X[0],A[0]),Solve(N,M,3,X[1],A[1]),Solve(N,M,2,X[2],A[2])};
    double ANS = -inf;
    rep(i,0,M+1) {
        rep(j,0,M+1) {
            if (i+j > M) break;
            chmax(ANS, D[0][i] + D[1][j] + D[2][M-i-j]);
        }
    }
    printf("%.12f\n",ANS);
}
accuracy: 1
time_ms: 270
memory_kb: 3696
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

vector<double> get_expected(int N, int M, int score, const vector<int>& A, const vector<double>& sp) {
	vector<double> res(M + 1);
	for (int i = 0; i <= M; i++) {
		vector<double> win(N);
		// win condition: A[0] * i > A[j] * x --> x < A[0] * i / A[j] --> x < ceil(A[0] * i / A[j])
		for (int j = 0; j < N; j++) {
			int b = (A[0] * i + A[j] - 1) / A[j];
			if (b > M + 1) {
				win[j] = 1.0;
			}
			else {
				win[j] = sp[b];
			}
		}
		array<double, 3> dp = { 1.0, 0.0, 0.0 };
		double worst = 1.0;
		for (int j = 1; j < N; j++) {
			array<double, 3> ndp = { 0.0, 0.0, 0.0 };
			for (int k = 0; k < 3; k++) {
				ndp[k] += dp[k] * win[j];
				if (k != 2) {
					ndp[k + 1] += dp[k] * (1.0 - win[j]);
				}
			}
			dp = ndp;
			worst *= (1.0 - win[j]);
		}
		res[i] = (dp[0] + dp[1] + dp[2]) * score - worst;
	}
	return res;
}

double solve(int N, int M, const vector<int>& A, const vector<int>& B, const vector<int>& C) {
	vector<vector<double> > p(M + 1);
	for (int i = 0; i <= M; i++) {
		p[i].resize(i + 1);
	}
	p[0][0] = 1.0;
	for (int i = 0; i < M; i++) {
		for (int j = 0; j <= i; j++) {
			p[i + 1][j] += p[i][j] * 2 / 3;
			p[i + 1][j + 1] += p[i][j] / 3;
		}
	}
	vector<double> sp(M + 2);
	for (int i = 0; i <= M; i++) {
		sp[i + 1] = sp[i] + p[M][i];
	}
	vector<double> ea = get_expected(N, M, 5, A, sp);
	vector<double> eb = get_expected(N, M, 3, B, sp);
	vector<double> ec = get_expected(N, M, 2, C, sp);
	double ans = -1.0e+99;
	for (int i = 0; i <= M; i++) {
		for (int j = 0; i + j <= M; j++) {
			int k = M - (i + j);
			double subscore = ea[i] + eb[j] + ec[k];
			ans = max(ans, subscore);
		}
	}
	return ans;
}

int main() {
	int N, M;
	cin >> N >> M;
	vector<int> A(N), B(N), C(N);
	for (int i = 0; i < N; i++) {
		cin >> A[i] >> B[i] >> C[i];
	}
	double ans = solve(N, M, A, B, C);
	cout.precision(15);
	cout << fixed << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 18916
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int N, A[2009], B[2009], C[2009];
int M;
double sum[2009][2009];
double dp[2009][4];
double ca[2009], cb[2009], cc[2009];

void Initialize() {
	sum[0][0] = 1;
	for (int i = 0; i < 2000; i++) {
		for (int j = 0; j < 2000; j++) {
			sum[i + 1][j + 0] += (2.0 / 3.0) * sum[i][j];
			sum[i + 1][j + 1] += (1.0 / 3.0) * sum[i][j];
		}
	}
	for (int i = 0; i <= 2000; i++) {
		for (int j = 2000; j >= 0; j--) sum[i][j] += sum[i][j + 1];
	}
}

pair<double, double> CalcProbability(int Target, vector<int> Points) {
	// Worst Probability
	double prob1 = 1;
	for (int i = 0; i < Points.size(); i++) {
		int num = min(2001, (Target + Points[i] - 1) / Points[i]);
		prob1 *= sum[M][num];
	}

	// Best Probability
	for (int i = 0; i <= Points.size(); i++) {
		for (int j = 0; j <= 3; j++) dp[i][j] = 0.0;
	}
	dp[0][0] = 1.0;
	for (int i = 0; i < Points.size(); i++) {
		for (int j = 0; j <= 3; j++) {
			int num = min(2001, (Target + Points[i] - 1) / Points[i]);
			double prob_ok = sum[M][num];
			double prob_ng = 1.0 - prob_ok;
			dp[i + 1][min(3, j + 0)] += dp[i][j] * prob_ng;
			dp[i + 1][min(3, j + 1)] += dp[i][j] * prob_ok;
		}
	}
	double prob2 = dp[Points.size()][3];

	// Return
	return make_pair(prob1, 1.0 - prob2);
}

int main() {
	// Step 1. Input
	Initialize();
	cin >> N >> M;
	for (int i = 1; i <= N; i++) cin >> A[i] >> B[i] >> C[i];

	// Step 2. Pre Calculation
	vector<int> LA, LB, LC;
	for (int i = 2; i <= N; i++) LA.push_back(A[i]);
	for (int i = 2; i <= N; i++) LB.push_back(B[i]);
	for (int i = 2; i <= N; i++) LC.push_back(C[i]);
	for (int i = 0; i <= M; i++) {
		pair<double, double> v1 = CalcProbability(A[1] * i, LA);
		pair<double, double> v2 = CalcProbability(B[1] * i, LB);
		pair<double, double> v3 = CalcProbability(C[1] * i, LC);
		ca[i] = 5.0 * v1.second - 1.0 * v1.first;
		cb[i] = 3.0 * v2.second - 1.0 * v2.first;
		cc[i] = 2.0 * v3.second - 1.0 * v3.first;
	}

	// Step 3. Brute Force
	double Answer = -1e9;
	for (int i = 0; i <= M; i++) {
		for (int j = 0; j <= M - i; j++) {
			int k = M - i - j;
			Answer = max(Answer, ca[i] + cb[j] + cc[k]);
		}
	}
	printf("%.12lf\n", Answer);
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 35092
final_rank: 11

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

vector<double> solve(const int n,const int m,const vector<double> &p,vector<int> v,int tmp){
    vector<double> res(m+1);
    for(int i=0;i<=m;i++){
        int score = v[0]*i;
        // 最下位の確率
        double bb = 1;
        array<double, 3> dp;
        dp[0] = 1;
        dp[1] = 0;
        dp[2] = 0;
        for(int j=1;j<n;j++){
            array<double, 3> ndp;
            ndp[0] = ndp[1] = ndp[2] = 0;
            double b;
            if(m*v[j] < score){
                b = 0;
            }
            else{
                int u = (score+v[j]-1)/v[j];
                b = p[u];
            }
            bb *= b;
            for(int k=0;k<3;k++){
                if(k+1<3){
                    ndp[k+1] += dp[k]*b;
                }
                ndp[k] += dp[k]*(1-b);
            }
            swap(dp,ndp);
        }
        res[i] = -bb+tmp*(dp[0]+dp[1]+dp[2]);
    }
    return res;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    vector<int> v(n),vv(n),vvv(n);
    for(int i=0;i<n;i++){
        cin >> v[i] >> vv[i] >> vvv[i];
    }
    vector<double> p(m+1);
    p[0] = 1.0;
    for(int i=0;i<m;i++){
        vector<double> np(m+1);
        for(int j=0;j<=i;j++){
            np[j+1] += p[j] / 3.0;
            np[j] += p[j] * 2.0 / 3.0;
        }
        swap(p,np);
    }
    for(int i=m;i>0;i--){
        p[i-1] += p[i];
    }
    auto r = solve(n,m,p,v,5);
    auto rr = solve(n,m,p,vv,3);
    auto rrr = solve(n,m,p,vvv,2);
    double res = -1e9;
    for(int i=0;i<=m;i++){
        for(int j=0;i+j<=m;j++){
            res = max(res,r[i]+rr[j]+rrr[m-i-j]);
        }
    }
    printf("%.9f\n",res);
}
accuracy: 1
time_ms: 40
memory_kb: 3664
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) os << v[i] << " ";
    return os;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int n, m;
    cin >> n >> m;
    vector<int> pts = {5, 3, 2};
    vector<vector<int>> val(n, vector<int>(3));
    for (auto& v : val) for (auto& x : v) cin >> x;
    vector<vector<double>> diff(3, vector<double>(m+1));

    // probability of appealing i times
    vector<double> prob(m+1);
    rep(j,0,m+1) {
        // prob[j] = pow(2.0/3, m);
        prob[j] = 1;
        rep(i,0,j) {
            prob[j] *= 1.0*(m-i)/(i+1)/3;
        }
        rep(i,0,m-j) prob[j] *= 2.0/3;
    }
    vector<double> cum(m+2);
    rep(j,0,m+1) cum[j+1] = cum[j] + prob[j];

    rep(k,0,3) {
        rep(j,0,m+1) {
            vector<double> p(n);
            rep(i,1,n) {
                // probability of the idol i beating the idol 0
                int c = (val[0][k]*j+val[i][k]-1)/val[i][k];
                // appeal k, >= c times
                if (c <= m) p[i] = 1.0 - cum[c];
            }
            vector<double> q(3);
            q[0] = 1;
            double alllose = 1;
            rep(i,1,n) {
                alllose *= p[i];
                vector<double> nq(3);
                rep(l,0,3) {
                    if (l+1 < 3) nq[l+1] += q[l] * p[i];
                    nq[l] += q[l] * (1-p[i]);
                }
                q.swap(nq);
            }
            diff[k][j] = accumulate(all(q), 0.0) * pts[k] - alllose;
        }
    }

    double ans = -1e18;
    rep(x,0,m+1) rep(y,0,m+1-x) {
        int z = m - (x + y);
        chmax(ans, diff[0][x] + diff[1][y] + diff[2][z]);
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 180
memory_kb: 3780
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) os << v[i] << " ";
    return os;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int n, m;
    cin >> n >> m;
    vector<int> pts = {5, 3, 2};
    vector<vector<int>> val(n, vector<int>(3));
    for (auto& v : val) for (auto& x : v) cin >> x;
    vector<vector<double>> diff(3, vector<double>(m+1));

    // probability of appealing i times
    vector<double> prob(m+1);
    rep(j,0,m+1) {
        prob[j] = pow(2.0/3, m);
        rep(i,0,j) {
            prob[j] *= 0.5*(m-i)/(i+1);
        }
    }
    vector<double> cum(m+2);
    rep(j,0,m+1) cum[j+1] = cum[j] + prob[j];

    rep(k,0,3) {
        rep(j,0,m+1) {
            vector<double> p(n);
            rep(i,1,n) {
                // probability of the idol i beating the idol 0
                int c = (val[0][k]*j+val[i][k]-1)/val[i][k];
                // appeal k, >= c times
                if (c <= m) p[i] = cum[m+1] - cum[c];
            }
            vector<double> q(3);
            q[0] = 1;
            double alllose = 1;
            rep(i,1,n) {
                alllose *= p[i];
                vector<double> nq(3);
                rep(l,0,3) {
                    if (l+1 < 3) nq[l+1] += q[l] * p[i];
                    nq[l] += q[l] * (1-p[i]);
                }
                q.swap(nq);
            }
            diff[k][j] = accumulate(all(q), 0.0) * pts[k] - alllose;
        }
    }

    double ans = -1e18;
    rep(x,0,m+1) rep(y,0,m+1-x) {
        int z = m - (x + y);
        chmax(ans, diff[0][x] + diff[1][y] + diff[2][z]);
    }
    cout << ans << endl;
}
accuracy: 0.5789473684210527
time_ms: 130
memory_kb: 4056
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) os << v[i] << " ";
    return os;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int n, m;
    cin >> n >> m;
    vector<int> pts = {5, 3, 2};
    vector<vector<int>> val(n, vector<int>(3));
    for (auto& v : val) for (auto& x : v) cin >> x;
    vector<vector<double>> diff(3, vector<double>(m+1));

    // probability of appealing i times
    vector<double> prob(m+1);
    rep(j,0,m+1) {
        double num = pow(2, m-j), den = pow(3, m);
        rep(i,0,j) {
            num *= (m-i);
            den *= i+1;
        }
        prob[j] = num/den;
    }
    vector<double> cum(m+2);
    rep(j,0,m+1) cum[j+1] = cum[j] + prob[j];

    rep(k,0,3) {
        rep(j,0,m+1) {
            vector<double> p(n);
            rep(i,1,n) {
                // probability of the idol i beating the idol 0
                int c = (val[0][k]*j+val[i][k]-1)/val[i][k];
                // appeal k, >= c times
                if (c <= m) p[i] = cum[m+1] - cum[c];
            }
            vector<double> q(3);
            q[0] = 1;
            double alllose = 1;
            rep(i,1,n) {
                alllose *= p[i];
                vector<double> nq(3);
                rep(l,0,3) {
                    if (l+1 < 3) nq[l+1] += q[l] * p[i];
                    nq[l] += q[l] * (1-p[i]);
                }
                q.swap(nq);
            }
            diff[k][j] = accumulate(all(q), 0.0) * pts[k] - alllose;
        }
    }

    double ans = -1e18;
    rep(x,0,m+1) rep(y,0,m+1-x) {
        int z = m - (x + y);
        chmax(ans, diff[0][x] + diff[1][y] + diff[2][z]);
    }
    cout << ans << endl;
}
accuracy: 0.47368421052631576
time_ms: 20
memory_kb: 4004
final_rank: 19

code_snippet: /*	author:  Kite_kuma
	created: 2022.03.01 23:02:29 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

double solve(int n) {
	int m;
	cin >> m;
	const int r = 3;
	VVEC(int, scores, n, r);
	const vector<int> pts = {5, 3, 2};

	vector<vector<int>> transpose(r, vi(n));
	rep(i, r) rep(j, n) transpose[i][j] = scores[j][i];

	const double trip = 1. / 3;

	vector<double> dp(m + 1, 0.);
	dp.front() = 1;
	rep(i, m) {
		auto pre = dp;
		dp.assign(m + 1, 0.);
		rep(j, i + 1) {
			dp[j] += (1 - trip) * pre[j];
			dp[j + 1] += (trip)*pre[j];
		}
	}

	vector<double> acc(m + 2);
	rep(i, m + 1) acc[i + 1] = acc[i] + dp[i];

	auto last_prob = [&](int score, vi &ab) {
		const int n = ab.size();
		double ret = 1;
		rep(i, 1, n) {
			int value = ab[i];
			int need = dup(score, value);
			chmin(need, m + 1);
			ret *= (1 - acc[need]);
		}
		return ret;
	};

	auto bestthree_prob = [&](int score, vi &ab) {
		const int len = ab.size();
		vector<double> ret(3);
		ret.front() = 1;
		rep(i, 1, len) {
			const int value = ab[i];
			int need = dup(score, value);
			chmin(need, m + 1);
			double under = acc[need];
			auto pre = ret;
			ret.assign(r, 0);
			rep(j, r) {
				ret[j] += under * pre[j];
				if(j < r - 1) ret[j + 1] += (1 - under) * pre[j];
			}
		}
		double value = accumulate(all(ret), double(0));
		return value;
	};

	vector<V<double>> pre_calced(r, V<double>(m+1));



	auto f = [&](int score, vi &abilities, int mult) {
		const int n = abilities.size();
		double ret = 0;
		ret += bestthree_prob(score, abilities) * mult;
		ret -= last_prob(score, abilities) * 1;
		return ret;
	};

	rep(i,r ){
		rep(cnt, 0, m+1){
			pre_calced[i][cnt] = f(cnt *scores.front().at(i), transpose[i], pts[i]);
		}
	}

	auto calc_score = [&](vector<int> &count) -> double {
		double ret = 0;
		// rep(i, r) {
		// 	int sc = count[i] * scores.front().at(i);
		// 	ret += f(sc, transpose[i], pts[i]);
		// }
		rep(i,r ){
			int cnt = count[i];
			ret += pre_calced[i][cnt];
		}
		return ret;
	};

	double ans = -INF;
	vector<int> count(r);
	for(count[0] = 0; count[0] <= m; count[0]++) {
		for(count[1] = 0; count[1] + count[0] <= m; count[1]++) {
			count[2] = m - count[0] - count[1];
			chmax(ans, calc_score(count));
		}
	}
	return ans;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n) {
		cout << solve(n) << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 3768
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

vector<long double> sub(int n, int m, const vector<long double> &ap,
                        const vector<int> &a, int point) {
  auto dp = vect(m + 1, (long double)0.0);
  for (int i = 0; i <= m; i++) {
    int x = a[0] * i;
    long double bottom = 1.0;

    vector<int> needed(n);
    for (int j = 1; j < n; j++) {
      needed[j] = min(m + 1, (x + a[j] - 1) / a[j]);
      bottom *= ap[needed[j]];
    }

    auto ep = vect(n + 1, vect(3, (long double)0.0));
    ep[1][0] = 1.0;
    for (int j = 1; j < n; j++) {
      for (int k = 0; k < 3; k++) {
        ep[j + 1][k] += ep[j][k] * (1.0 - ap[needed[j]]);
        if (k + 1 < 3) ep[j + 1][k + 1] += ep[j][k] * ap[needed[j]];
      }
    }
    dp[i] = (ep[n][0] + ep[n][1] + ep[n][2]) * point - bottom;
  }
  return dp;
}

void solve() {
  int n, m;
  cin >> n >> m;
  vector<int> a(n), b(n), c(n);
  for (int i = 0; i < n; i++) { cin >> a[i] >> b[i] >> c[i]; }

  auto ap = vect(m + 2, (long double)0.0);
  ap[0] = 1.0;
  for (int i = 0; i < m; i++) ap[0] *= 2.0 / 3.0;
  for (int i = 1; i <= m; i++) { ap[i] = ap[i - 1] / 2.0 * (m - i + 1) / i; }
  for (int i = m - 1; i >= 0; i--) ap[i] += ap[i + 1];

  auto dp = sub(n, m, ap, a, 5);
  auto ep = sub(n, m, ap, b, 3);
  auto fp = sub(n, m, ap, c, 2);
  dmp(dp);

  auto gp = vect(m + 1, (long double)-10.0);
  for (int i = 0; i <= m; i++) {
    for (int j = 0; j <= m; j++) {
      if (i + j > m) break;
      chmax(gp[i + j], dp[i] + ep[j]);
    }
  }

  long double ans = -10.0;
  for (int i = 0; i <= m; i++) { chmax(ans, gp[i] + fp[m - i]); }

  cout << ans << endl;

  return;
}

int main() {
  fastio();
  if (!multitest) {
    solve();
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 500
memory_kb: 3816
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using PII = pair<ll, ll>;
using T = tuple<int, int, int>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

const ull MOD = 1e9 + 7;

// BEGIN CUT
ll modpow(ll x, ll y, ll m) {
    ll a = 1, p = x;
    while (y > 0) {
        if (y % 2 == 0) {
            p = (p * p) % m;
            y /= 2;
        } else {
            a = (a * p) % m;
            y--;
        }
    }
    return a;
}
// END CUT

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

int vi[2000], da[2000], vo[2000];
double res_vi[2001], res_da[2001], res_vo[2001];
double prob[2001];
double dp[2001][2];
double lose[2001];

void calc(int n, int m, int *idol, double *result, int wp) {
    for (int i = 0; i <= m; i++) {
        int V = idol[0] * i;
        vector<double> vec(n);
        for (int j = 1; j < n; j++) {
            int k = (V + idol[j] - 1) / idol[j];
            double win = 0;
            if (k <= m)
                win = prob[k];
            vec[j] = win;
        }
        dp[0][0] = 1, dp[0][1] = 0;
        for (int j = 1; j < n; j++) {
            dp[j][0] = dp[j - 1][0] * (1 - vec[j]);
            dp[j][1] = dp[j - 1][0] * vec[j] + dp[j - 1][1] * (1 - vec[j]);
        }
        lose[n] = 1;
        for (int j = n - 1; j >= 1; j--) {
            lose[j] = lose[j + 1] * (1 - vec[j]);
        }
        double p = dp[n - 1][0] + dp[n - 1][1];
        for (int j = 1; j < n; j++) {
            p += vec[j] * dp[j - 1][1] * lose[j + 1];
        }
        result[i] = p * wp;
        double q = 1;
        for (int j = 1; j < n; j++)
            q *= vec[j];
        result[i] -= q;
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> vi[i] >> da[i] >> vo[i];

    prob[0] = 1;
    for (int i = 1; i <= m; i++) {
        prob[i] = prob[i - 1] * (m - i + 1) / i;
        prob[i] /= 3;
    }
    double tmp = 1;
    for (int i = m; i >= 0; i--) {
        prob[i] *= tmp;
        tmp *= 2.0 / 3.0;
    }
    for (int i = m - 1; i >= 0; i--)
        prob[i] += prob[i + 1];
    calc(n, m, vi, res_vi, 5);
    calc(n, m, da, res_da, 3);
    calc(n, m, vo, res_vo, 2);
    double ans = -1e9;
    for (int i = 0; i <= m; i++) {
        for (int j = 0; i + j <= m; j++) {
            double sum = res_vi[i] + res_da[j] + res_vo[m - (i + j)];
            ans = max(ans, sum);
        }
    }
    cout << fixed << setprecision(15) << ans << '\n';
}
accuracy: 1
time_ms: 120
memory_kb: 3732
final_rank: 3

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long MOD = 1000000007;
//constexpr long long MOD = 998244353;
constexpr double EPS = 1e-6;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N >> M;
	vector<vector<int>>v(N, vector<int>(3));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < 3; j++) {
			cin >> v[i][j];
		}
	}
	vector<vector<long double>>p(M + 1, vector<long double>(M + 1));
	p[0][0] = 1;
	for (int i = 0; i < M; i++) {
		for (int j = 0; j <= i; j++) {
			p[i + 1][j + 1] += p[i][j] / 3;
			p[i + 1][j] += p[i][j] * 2 / 3;
		}
	}
	for (int i = 1; i <= M; i++) {
		for (int j = M - 1; j >= 0; j--) {
			p[i][j] += p[i][j + 1];
		}
	}
	int by[] = { 5,3,2 };
	vector<long double>dp(M + 1);
	for (int i = 0; i < 3; i++) {
		vector<long double>box(M + 1);
		box[0] = -1;
		for (int j = 1; j <= M; j++) {
			long double worst = 1;
			vector<long double>rank(3);
			rank[0] = 1;
			for (int k = 1; k < N; k++) {
				int num = j * v[0][i];
				num = (num + v[k][i] - 1) / v[k][i];
				long double q = 0;
				if (num > M) {
					q = 0;
				}
				else {
					q = p[M][num];
				}
				worst *= q;
				rank[2] = rank[2] * (1 - q) + rank[1] * q;
				rank[1] = rank[1] * (1 - q) + rank[0] * q;
				rank[0] *= 1 - q;
			//	cout << i << " " << j << " " << k << " " << worst << " " << num << endl;
			}
			box[j] -= worst;
			box[j] += (rank[0] + rank[1] + rank[2]) * by[i];
		}
		vector<long double>nxdp(M + 1,-5);
		for (int j = 0; j <= M; j++) {
			for (int k = 0; k + j <= M; k++) {
				nxdp[j + k] = max(nxdp[j + k], dp[j] + box[k]);
			}
		}
		dp = nxdp;
	}
	cout << fixed << setprecision(20) << dp.back() << endl;
}
accuracy: 1
time_ms: 150
memory_kb: 66260
final_rank: 14

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
//const int mod = 1e9 + 7;
const int mod = 998244353;

int main(){
    int n,m; cin >> n >> m;
    vvl a(n,vl(3));
    rep(i,n) rep(j,3) cin >> a[i][j];
    vl bonus{5,3,2};
    vector<vd> res(m+1,vd(3,0));
    vd prob(m+2,0);
    prob[0] = 1;
    rep(i,m){
        vd np(m+2,0);
        rep(j,m+1){
            np[j+1] += prob[j] / 3;
            np[j] += prob[j] * 2 / 3;
        }
        swap(prob,np);
    }
    for(int i=m-1; i>=0; i--) prob[i] += prob[i+1];
    rep(i,m+1) rep(j,3){
        vector<vd> dp(2,vd(4,0));
        dp[0][0] = 1;
        double all_lose = 1;
        REP(k,1,n){
            rep(l,4) dp[1][l] = 0;
            int t = (a[0][j]*i+a[k][j]-1) / a[k][j];
            double p = t<=m ? prob[t] : 0;
            chmin(p,1);
            rep(l,4){
                dp[1][l] += dp[0][l] * (1-p);
                dp[1][min(3,l+1)] += dp[0][l] * p;
            }
            all_lose *= p;
            swap(dp[0],dp[1]);
        }
        res[i][j] = (dp[0][0]+dp[0][1]+dp[0][2]) * bonus[j] - all_lose;
    }
    double ans = -inf;
    rep(i,m+1) rep(j,m+1){
        if(i+j>m) break;
        int k = m-i-j;
        chmax(ans, res[i][0] + res[j][1] + res[k][2]);
    }
    printf("%.10f\n",ans);
}
accuracy: 1
time_ms: 160
memory_kb: 3788
final_rank: 5

code_snippet: #include<bits/stdc++.h>
#define ALL(A) A.begin(),A.end()
using namespace std;
namespace BIN101{
using ll=long long int;
//using Int=__int128;
template<typename T1,typename T2> bool chmin(T1 &a,T2 b){if(a<=b)return 0; a=b; return 1;}
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}
template<typename T> constexpr int bitUP(T x,int a){return (x>>a)&1;}
//→　↓　←　↑ 
//int dh[4]={0,1,0,-1}, dw[4]={1,0,-1,0};
//右上から時計回り
int dx[8]={1,1,0,-1,-1,-1,0,+1}, dy[8]={0,1,1,1,0,-1,-1,-1};
long double EPS = 1e-6;
long double PI = acos(-1);
const ll INF=numeric_limits<ll>::max()/3;
const int MAX=numeric_limits<int>::max()/3;
constexpr ll MOD=1000000000+7;
//constexpr ll MOD=998244353;
vector<ll> ten(18+1);


inline void bin101(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);
    ten[0]=1;
    for(int i=1;i<=18;i++) ten[i]=ten[i-1]*10;
}

using pii=pair<int,int>;
using pil=pair<int,ll>;
using pli=pair<ll,int>;
using pll=pair<ll,ll>;
using psi=pair<string,int>;
using pis=pair<int,string>;
using psl=pair<string,ll>;
using pls=pair<ll,string>;
using pss=pair<string,string>;

using Graph=vector<vector<int>>;

template<typename T >
struct edge {
	int to;
	T cost;
	edge()=default;
	edge(int to, T cost) : to(to), cost(cost) {}

};
template<typename T>
using WeightGraph=vector<vector<edge<T>>>;

template<typename T>
void CinGraph(int M,WeightGraph<T> &g,bool directed=false,bool index1=true){
    while(M--){
        int s,t;
        T cost;
        cin>>s>>t>>cost;
        if(index1) s--,t--;
        g[s].emplace_back(t,cost);
        if(not directed) g[t].emplace_back(s,cost);
    }
}

void CinGraph(int M,Graph &g,bool directed=false,bool index1=true){
    while(M--){
        int s,t;
        cin>>s>>t;
        if(index1) s--,t--;
        g[s].push_back(t);
        if(not directed) g[t].push_back(s);
    }
}


//0-indexed vector cin
template<typename T>
inline istream &operator>>(istream &is,vector<T> &v) {
    for(size_t i=0;i<v.size();i++) is>>v[i];
	return is;
}
 
//0-indexed vector cin
template<typename T>
inline istream &operator>>(istream &is,vector<vector<T>> &v) {
    for(size_t i=0;i<v.size();i++){
        is>>v[i];
    }
    return is;
}
//vector cout
template<typename T>
inline ostream &operator<<(ostream &os,const vector<T> &v) {
    for(size_t i=0;i<v.size();i++){
        if(i) os<<" ";
        os<<v[i];
    }
    return os;
}
//vector<vector> cout
template<typename T>
inline ostream &operator<<(ostream &os,const vector<vector<T>> &v) {
    for(size_t i=0;i<v.size();i++){
        os<<v[i];
        if(i+1!=v.size()) os<<"\n";
    }
    return os;
}

//Graph out
template<typename T>
inline ostream &operator<<(ostream &os,const Graph &g) {
    for(size_t i=0;i<g.size();i++){
        for(int to:g[i]){
            os<<i<<"->"<<to<<" ";
        }
        os<<endl;
    }
    return os;
}

//WeightGraph out
template<typename T>
inline ostream &operator<<(ostream &os,const WeightGraph<T> &g) {
    for(size_t i=0;i<g.size();i++){
        for(auto e:g[i]){
            os<<i<<"->"<<e.to<<"("<<e.cost<<") ";
        }
        os<<endl;
    }
    return os;
}


//要素数n 初期値x
template<typename T>
inline vector<T> vmake(size_t n,T x){
	return vector<T>(n,x);
}

//a,b,c,x data[a][b][c] 初期値x
template<typename... Args>
auto vmake(size_t n,Args... args){
	auto v=vmake(args...);
	return vector<decltype(v)>(n,move(v));
}

//pair cout
template<typename T, typename U>
inline ostream &operator<<(ostream &os,const pair<T,U> &p) {
	os<<p.first<<" "<<p.second;
	return os;
}
 
//pair cin
template<typename T, typename U>
inline istream &operator>>(istream &is,pair<T,U> &p) {
	is>>p.first>>p.second;
	return is;
}
 
//ソート
template<typename T>
inline void vsort(vector<T> &v){
    sort(v.begin(),v.end());
}
 
//逆順ソート
template<typename T>
inline void rvsort(vector<T> &v){
	sort(v.rbegin(),v.rend());
}

//1ビットの数を返す
inline int popcount(int x){
	return __builtin_popcount(x);
}
//1ビットの数を返す
inline int popcount(ll x){
	return __builtin_popcountll(x);
}
template<typename T>
inline void Compress(vector<T> &C){
    sort(C.begin(),C.end());
    C.erase(unique(C.begin(),C.end()),C.end());
}
template<typename T>
inline int lower_idx(const vector<T> &C,T value){
    return lower_bound(C.begin(),C.end(),value)-C.begin();
}
template<typename T>
inline int upper_idx(const vector<T> &C,T value){
    return upper_bound(C.begin(),C.end(),value)-C.begin();
}
//時計回りに90度回転
template<typename T>
inline void rotate90(vector<vector<T>> &C){
    vector<vector<T>> D(C[0].size(),vector<T>(C.size()));
    for(int h=0;h<C.size();h++){
        for(int w=0;w<C[h].size();w++){
            D[w][C.size()-1-h]=C[h][w];
        }
    }
    C=D;
}
//補グラフを返す
//i→iのような辺は加えない
Graph ComplementGraph(const Graph &g){
    size_t sz=g.size();
    bool used[sz][sz];
    fill(used[0],used[sz],false);
    for(size_t i=0;i<sz;i++){
        for(int to:g[i]){
            used[i][to]=true;
        }
    }
    Graph ret(sz);
    for(size_t i=0;i<sz;i++){
        for(size_t j=0;j<sz;j++){
            if(used[i][j]) continue;
            if(i==j) continue;
            ret[i].push_back(j);
        }
    }
    return ret;
}
//グラフの分解 secondはある頂点がどこに対応するか id[i]={2,3}のとき,頂点iはret[2][3]に対応
//無効グラフのみに対応
pair<vector<Graph>,vector<pair<int,int>>> GraphDecomposition(const Graph &g){
    vector<pair<int,int>> id(g.size(),pair<int,int>(-1,-1));
    vector<Graph> ret;
    vector<int> now;
    for(size_t i=0;i<g.size();i++){
        if(id[i].first!=-1) continue;
        id[i].first=ret.size();
        id[i].second=0;
        now.push_back(i);
        for(size_t j=0;j<now.size();j++){
            for(int to:g[now[j]]){
                if(id[to].first==-1){
                    id[to].first=ret.size();
                    id[to].second=now.size();
                    now.push_back(to);
                }
            }
        }
        Graph r(now.size());
        for(size_t j=0;j<now.size();j++){
            r[j]=g[now[j]];
            for(int &to:r[j]){
                to=id[to].second;
            }
        }
        ret.push_back(r);
        now.clear();
    }
    return make_pair(ret,id);
}
//0indexを想定
bool OutGrid(ll h,ll w,ll H,ll W){
    return (h>=H or w>=W or h<0 or w<0);
}

void NO(){
    cout<<"NO"<<"\n";
}
void YES(){
    cout<<"YES"<<"\n";
}
void No(){
    cout<<"No"<<"\n";
}
void Yes(){
    cout<<"Yes"<<"\n";
}
namespace overflow{
    template<typename T>
    T max(){
        return numeric_limits<T>::max();
    }
    template<typename T>
    T ADD(T a,T b){
        T res;
        return __builtin_add_overflow(a,b,&res)?max<T>():res;
    }
    template<typename T>
    T MUL(T a,T b){
        T res;
        return __builtin_mul_overflow(a,b,&res)?max<T>():res;
    }
};
using namespace overflow;
struct ModInt{
    using u64=uint_fast64_t;
    u64 a;
    constexpr ModInt() :a(0){}
    constexpr ModInt(ll x) :a((x>=0)?(x%MOD):(x%MOD+MOD) ) {}

    inline constexpr ModInt operator+(const ModInt rhs)const noexcept{
        return ModInt(*this)+=rhs;
    }
    inline constexpr ModInt operator-(const ModInt rhs)const noexcept{
        return ModInt(*this)-=rhs;
    }
    inline constexpr ModInt operator*(const ModInt rhs)const noexcept{
        return ModInt(*this)*=rhs;
    }
    inline constexpr ModInt operator/(const ModInt rhs)const noexcept{
        return ModInt(*this)/=rhs;
    }
    inline constexpr ModInt operator+(const ll rhs) const noexcept{
        return ModInt(*this)+=ModInt(rhs);
    }
    inline constexpr ModInt operator-(const ll rhs)const noexcept{
        return ModInt(*this)-=ModInt(rhs);
    }
    inline constexpr ModInt operator*(const ll rhs)const noexcept{
        return ModInt(*this)*=ModInt(rhs);
    }
    inline constexpr ModInt operator/(const ll rhs)const noexcept{
        return ModInt(*this)/=ModInt(rhs);
    }

    inline constexpr ModInt &operator+=(const ModInt rhs)noexcept{
        a+=rhs.a;
        if(a>=MOD) a-=MOD;
        return *this;
    }
    inline constexpr ModInt &operator-=(const ModInt rhs)noexcept{
        if(rhs.a>a) a+=MOD;
        a-=rhs.a;
        return *this;
    }
    inline constexpr ModInt &operator*=(const ModInt rhs)noexcept{
        a=(a*rhs.a)%MOD;
        return *this;
    }
    inline constexpr ModInt &operator/=(ModInt rhs)noexcept{
        a=(a*rhs.inverse().a)%MOD;
        return *this;
    }
    inline constexpr ModInt &operator+=(const ll rhs)noexcept{
        return *this+=ModInt(rhs);
    }
    inline constexpr ModInt &operator-=(const ll rhs)noexcept{
        return *this-=ModInt(rhs);
    }
    inline constexpr ModInt &operator*=(const ll rhs)noexcept{
        return *this*=ModInt(rhs);
    }
    inline constexpr ModInt &operator/=(const ll rhs)noexcept{
        return *this/=ModInt(rhs);
    }

    inline constexpr ModInt operator=(const ll x)noexcept{
        a=(x>=0)?(x%MOD):(x%MOD+MOD);
        return *this;
    }

    inline constexpr bool operator==(const ModInt p)const noexcept{
        return a==p.a;
    }

    inline constexpr bool operator!=(const ModInt p)const noexcept{
        return a!=p.a;
    }

    inline constexpr ModInt pow(ll N) const noexcept{
        ModInt ans(1LL),p(a);
        while(N>0){
            if(bitUP(N,0)){
                ans*=p;
            }
            p*=p;
            N>>=1;
        }
        return ans;
    }
    inline constexpr ModInt inverse() const noexcept{
        return pow(MOD-2);
    }

};
inline constexpr ModInt operator+(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)+=b;
}
inline constexpr ModInt operator-(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)-=b;
}
inline constexpr ModInt operator*(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)*=b;
}
inline constexpr ModInt operator/(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)/=b;
}
//cout
inline ostream &operator<<(ostream &os,const ModInt &p) {
    return os<<p.a;
}

//cin
inline istream &operator>>(istream &is,ModInt &p) {
    ll t;
    is>>t;
    p=t;
    return is;
}

struct Binominal{
    vector<ModInt> fac,finv,inv; //fac[n]:n! finv:(n!)の逆元
    int sz;
    Binominal(int n=10) :sz(1){
        if(n<=0) n=10;
        init(n);
    }
    inline void init(int n){
        fac.resize(n+1,1);
        finv.resize(n+1,1);
        inv.resize(n+1,1);
        for(int i=sz+1;i<=n;i++){
            fac[i]=fac[i-1]*i;
            inv[i]=MOD-inv[MOD%i]*(MOD/i);
            finv[i]=finv[i-1]*inv[i];
        }
        sz=n;
    }
    //nCk(n,k<=N) をO(1)で求める
    inline ModInt com(int n,int k){
        if(k==0 or k==n) return 1;
        if(n<k) return ModInt(0);
        if(n<0 || k<0) return ModInt(0);
        if(n>sz) init(n);
        return fac[n]*finv[k]*finv[n-k];
    }
    //nCk(k<=N) をO(k)　で求める 
    inline ModInt rcom(ll n,int k){
        if(n<0 || k<0 || n<k) return ModInt(0);
        if(k>sz) init(k);
        ModInt ret(1);
        for(int i=0;i<k;i++){
            ret*=n-i;
        }
        ret*=finv[k];
        return ret;
    }

    //重複組み合わせ n種類のものから重複を許してk個を選ぶ
    //〇がn個,|がk個
    inline ModInt h(int n,int k){
        return com(n+k-1,k);
    }
    //power[N+1] (power[i]=x^i)を返す
    static vector<ModInt> MakePower(ll x,int N){
        vector<ModInt> ret(N+1);
        ret[0]=1;
        for(int i=1;i<=N;i++){
            ret[i]=ret[i-1]*x;
        }
        return ret;
    }
};
vector<int> Subset(int S,bool zero=false,bool full=false){
    vector<int> ret;
    int now=(S-1)&S;
    if(full and S){
        ret.push_back(S);
    }
    do{
        ret.push_back(now);
        now=(now-1)&S;
    }while(now!=0);
    if(zero){
        ret.push_back(0);
    }
    return ret;
}

//xと差が最小の値を持つ添え字を返す
//xはソート済みを想定
//1つだけ返す
template<typename T>
inline int MinimumAbs(vector<T> &v,T x){
    assert(v.size());
    auto large=lower_bound(v.begin(),v.end(),x);
    auto small=large;
    if(large==v.begin()) return large-v.begin();
    if(large==v.end()) return v.size()-1;
    small--;
    if(abs(*small-x)>abs(*large-x)) small=large;
    return small-v.begin();
}


class modint{
    using u64=uint_fast64_t;
    static u64 &mod(){
        static u64 mod_=0;
        return mod_;
    }
public:
    u64 a;
    modint(const ll x=0):a((x>=0)?(x%mod()):(x%mod()+mod())){}
    modint operator+(const modint rhs)const{
        return modint(*this)+=rhs;
    }
    modint operator-(const modint rhs)const{
        return modint(*this)-=rhs;
    }
    modint operator*(const modint rhs)const{
        return modint(*this)*=rhs;
    }
    modint operator/(const modint rhs)const{
        return modint(*this)/=rhs;
    }
    modint &operator+=(const modint rhs){
        a+=rhs.a;
        if(a>=mod()) a-=mod();
        return *this;
    }
    modint &operator-=(const modint rhs){
        if(a<rhs.a) a+=mod();
        a-=rhs.a;
        return *this;
    }
    modint &operator*=(const modint rhs){
        a=a*rhs.a%mod();
        return *this;
    }
    modint &operator/=(const modint rhs){
        a=(a*rhs.inverse().a)%mod();
        return *this;
    }
    inline modint &operator+=(const ll rhs){
        return *this+=modint(rhs);
    }
    inline modint &operator-=(const ll rhs){
        return *this-=modint(rhs);
    }
    inline modint &operator*=(const ll rhs){
        return *this*=modint(rhs);
    }
    inline modint &operator/=(const ll rhs){
        return *this/=modint(rhs);
    }

    inline modint pow(u64 N)const{
        modint ans(1LL),p(a);
        while(N>0){
            if(bitUP(N,0)){
                ans*=p;
            }
            p*=p;
            N>>=1;
        }
        return ans;
    }
    inline modint inverse()const{
        return pow(mod()-2);
    }
    inline modint operator=(const ll x){
        a=(x>=0)?(x%mod()):(x%mod()+mod());
        return *this;
    }

    static void set_mod(const u64 x){mod()=x;}
    static u64 get_mod(){return mod();}
};
inline modint operator+(const ll a,const modint b)noexcept{
    return modint(a)+=b;
}
inline modint operator-(const ll a,const modint b)noexcept{
    return modint(a)-=b;
}
inline modint operator*(const ll a,const modint b)noexcept{
    return modint(a)*=b;
}
inline modint operator/(const ll &a,const modint &b)noexcept{
    return modint(a)/=b;
}
//cout
inline ostream &operator<<(ostream &os,const modint &p) {
    return os<<p.a;
}

//cin
inline istream &operator>>(istream &is,modint &p) {
    ll t;
    is>>t;
    p=t;
    return is;
}
template<class T>
vector<vector<T>> Binominal(int n){
    vector<vector<T>> table(n+1,vector<T>(n+1,0));
    table[0][0]=1;
    for(int i=1;i<=n;i++){
        table[i][0]=1;
        for(int j=1;j<=i;j++){
            table[i][j]=table[i-1][j-1]+table[i-1][j];
        }
    }
    return table;
};

void solve(){
    int N,M;
    cin>>N>>M;
    auto power=vmake(N,3,0);
    for(int i=0;i<N;i++){
        for(int j=0;j<3;j++) cin>>power[i][j];
    }
    using DD=long double;
    vector<DD> prob(M+100);
    auto B=Binominal<DD>(M+100);
    DD zen=0;
    for(int a=0;a<=M;a++){
        for(int b=0;b<=M;b++){
            if(a+b>M) continue;
            zen+=B[M][a]*B[M-a][b];
        }
    }
    for(int i=M;i>=0;i--){
        if(i!=M) prob[i]=prob[i+1];
        for(int j=0;j+i<=M;j++){
            prob[i]+=B[M][i]*B[M-i][j]/zen;
        }
    }
    auto point=vmake(3,M+1,(DD)0);
    for(int i=0;i<3;i++){
        for(int m=0;m<=M;m++){
            DD sai=1.0;
            auto dp=vmake(3,(DD)0);
            dp[0]=1;
            int p=power[0][i]*m;
            for(int k=1;k<N;k++){
                //負ける確率を求める
                int tp=power[k][i];
                int cnt=(p+tp-1)/tp;
                DD pb=0;
                if(cnt<=M) pb=prob[cnt];
                sai*=pb;
                for(int j=2;j>=0;j--){
                    if(j<=1) dp[j+1]+=dp[j]*pb;
                    dp[j]=dp[j]*(1-pb);
                }
            }
            DD ret=0;
            ret+=sai*(-1);
            DD x=5;
            if(i==1) x=3;
            else if(i==2) x=2;
            ret+=x*(dp[0]+dp[1]+dp[2]);
            point[i][m]=ret;
        }
    }
    DD ans=-MAX;
    for(int a=0;a<=M;a++){
        for(int b=0;b<=M;b++){
            if(a+b>M) continue;
            chmax(ans,point[0][a]+point[1][b]+point[2][M-a-b]);
        }
    }
    cout<<ans<<endl;
}

};

int main(){
    BIN101::bin101();
    int T=1;
    //cin>>T;
    while(T--) BIN101::solve();
}
accuracy: 1
time_ms: 200
memory_kb: 72632
final_rank: 16

code_snippet: #include<bits/stdc++.h>
#define ALL(A) A.begin(),A.end()
using namespace std;
namespace BIN101{
using ll=long long int;
//using Int=__int128;
template<typename T1,typename T2> bool chmin(T1 &a,T2 b){if(a<=b)return 0; a=b; return 1;}
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}
template<typename T> constexpr int bitUP(T x,int a){return (x>>a)&1;}
//→　↓　←　↑ 
//int dh[4]={0,1,0,-1}, dw[4]={1,0,-1,0};
//右上から時計回り
int dx[8]={1,1,0,-1,-1,-1,0,+1}, dy[8]={0,1,1,1,0,-1,-1,-1};
long double EPS = 1e-6;
long double PI = acos(-1);
const ll INF=numeric_limits<ll>::max()/3;
const int MAX=numeric_limits<int>::max()/3;
constexpr ll MOD=1000000000+7;
//constexpr ll MOD=998244353;
vector<ll> ten(18+1);


inline void bin101(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);
    ten[0]=1;
    for(int i=1;i<=18;i++) ten[i]=ten[i-1]*10;
}

using pii=pair<int,int>;
using pil=pair<int,ll>;
using pli=pair<ll,int>;
using pll=pair<ll,ll>;
using psi=pair<string,int>;
using pis=pair<int,string>;
using psl=pair<string,ll>;
using pls=pair<ll,string>;
using pss=pair<string,string>;

using Graph=vector<vector<int>>;

template<typename T >
struct edge {
	int to;
	T cost;
	edge()=default;
	edge(int to, T cost) : to(to), cost(cost) {}

};
template<typename T>
using WeightGraph=vector<vector<edge<T>>>;

template<typename T>
void CinGraph(int M,WeightGraph<T> &g,bool directed=false,bool index1=true){
    while(M--){
        int s,t;
        T cost;
        cin>>s>>t>>cost;
        if(index1) s--,t--;
        g[s].emplace_back(t,cost);
        if(not directed) g[t].emplace_back(s,cost);
    }
}

void CinGraph(int M,Graph &g,bool directed=false,bool index1=true){
    while(M--){
        int s,t;
        cin>>s>>t;
        if(index1) s--,t--;
        g[s].push_back(t);
        if(not directed) g[t].push_back(s);
    }
}


//0-indexed vector cin
template<typename T>
inline istream &operator>>(istream &is,vector<T> &v) {
    for(size_t i=0;i<v.size();i++) is>>v[i];
	return is;
}
 
//0-indexed vector cin
template<typename T>
inline istream &operator>>(istream &is,vector<vector<T>> &v) {
    for(size_t i=0;i<v.size();i++){
        is>>v[i];
    }
    return is;
}
//vector cout
template<typename T>
inline ostream &operator<<(ostream &os,const vector<T> &v) {
    for(size_t i=0;i<v.size();i++){
        if(i) os<<" ";
        os<<v[i];
    }
    return os;
}
//vector<vector> cout
template<typename T>
inline ostream &operator<<(ostream &os,const vector<vector<T>> &v) {
    for(size_t i=0;i<v.size();i++){
        os<<v[i];
        if(i+1!=v.size()) os<<"\n";
    }
    return os;
}

//Graph out
template<typename T>
inline ostream &operator<<(ostream &os,const Graph &g) {
    for(size_t i=0;i<g.size();i++){
        for(int to:g[i]){
            os<<i<<"->"<<to<<" ";
        }
        os<<endl;
    }
    return os;
}

//WeightGraph out
template<typename T>
inline ostream &operator<<(ostream &os,const WeightGraph<T> &g) {
    for(size_t i=0;i<g.size();i++){
        for(auto e:g[i]){
            os<<i<<"->"<<e.to<<"("<<e.cost<<") ";
        }
        os<<endl;
    }
    return os;
}


//要素数n 初期値x
template<typename T>
inline vector<T> vmake(size_t n,T x){
	return vector<T>(n,x);
}

//a,b,c,x data[a][b][c] 初期値x
template<typename... Args>
auto vmake(size_t n,Args... args){
	auto v=vmake(args...);
	return vector<decltype(v)>(n,move(v));
}

//pair cout
template<typename T, typename U>
inline ostream &operator<<(ostream &os,const pair<T,U> &p) {
	os<<p.first<<" "<<p.second;
	return os;
}
 
//pair cin
template<typename T, typename U>
inline istream &operator>>(istream &is,pair<T,U> &p) {
	is>>p.first>>p.second;
	return is;
}
 
//ソート
template<typename T>
inline void vsort(vector<T> &v){
    sort(v.begin(),v.end());
}
 
//逆順ソート
template<typename T>
inline void rvsort(vector<T> &v){
	sort(v.rbegin(),v.rend());
}

//1ビットの数を返す
inline int popcount(int x){
	return __builtin_popcount(x);
}
//1ビットの数を返す
inline int popcount(ll x){
	return __builtin_popcountll(x);
}
template<typename T>
inline void Compress(vector<T> &C){
    sort(C.begin(),C.end());
    C.erase(unique(C.begin(),C.end()),C.end());
}
template<typename T>
inline int lower_idx(const vector<T> &C,T value){
    return lower_bound(C.begin(),C.end(),value)-C.begin();
}
template<typename T>
inline int upper_idx(const vector<T> &C,T value){
    return upper_bound(C.begin(),C.end(),value)-C.begin();
}
//時計回りに90度回転
template<typename T>
inline void rotate90(vector<vector<T>> &C){
    vector<vector<T>> D(C[0].size(),vector<T>(C.size()));
    for(int h=0;h<C.size();h++){
        for(int w=0;w<C[h].size();w++){
            D[w][C.size()-1-h]=C[h][w];
        }
    }
    C=D;
}
//補グラフを返す
//i→iのような辺は加えない
Graph ComplementGraph(const Graph &g){
    size_t sz=g.size();
    bool used[sz][sz];
    fill(used[0],used[sz],false);
    for(size_t i=0;i<sz;i++){
        for(int to:g[i]){
            used[i][to]=true;
        }
    }
    Graph ret(sz);
    for(size_t i=0;i<sz;i++){
        for(size_t j=0;j<sz;j++){
            if(used[i][j]) continue;
            if(i==j) continue;
            ret[i].push_back(j);
        }
    }
    return ret;
}
//グラフの分解 secondはある頂点がどこに対応するか id[i]={2,3}のとき,頂点iはret[2][3]に対応
//無効グラフのみに対応
pair<vector<Graph>,vector<pair<int,int>>> GraphDecomposition(const Graph &g){
    vector<pair<int,int>> id(g.size(),pair<int,int>(-1,-1));
    vector<Graph> ret;
    vector<int> now;
    for(size_t i=0;i<g.size();i++){
        if(id[i].first!=-1) continue;
        id[i].first=ret.size();
        id[i].second=0;
        now.push_back(i);
        for(size_t j=0;j<now.size();j++){
            for(int to:g[now[j]]){
                if(id[to].first==-1){
                    id[to].first=ret.size();
                    id[to].second=now.size();
                    now.push_back(to);
                }
            }
        }
        Graph r(now.size());
        for(size_t j=0;j<now.size();j++){
            r[j]=g[now[j]];
            for(int &to:r[j]){
                to=id[to].second;
            }
        }
        ret.push_back(r);
        now.clear();
    }
    return make_pair(ret,id);
}
//0indexを想定
bool OutGrid(ll h,ll w,ll H,ll W){
    return (h>=H or w>=W or h<0 or w<0);
}

void NO(){
    cout<<"NO"<<"\n";
}
void YES(){
    cout<<"YES"<<"\n";
}
void No(){
    cout<<"No"<<"\n";
}
void Yes(){
    cout<<"Yes"<<"\n";
}
namespace overflow{
    template<typename T>
    T max(){
        return numeric_limits<T>::max();
    }
    template<typename T>
    T ADD(T a,T b){
        T res;
        return __builtin_add_overflow(a,b,&res)?max<T>():res;
    }
    template<typename T>
    T MUL(T a,T b){
        T res;
        return __builtin_mul_overflow(a,b,&res)?max<T>():res;
    }
};
using namespace overflow;
struct ModInt{
    using u64=uint_fast64_t;
    u64 a;
    constexpr ModInt() :a(0){}
    constexpr ModInt(ll x) :a((x>=0)?(x%MOD):(x%MOD+MOD) ) {}

    inline constexpr ModInt operator+(const ModInt rhs)const noexcept{
        return ModInt(*this)+=rhs;
    }
    inline constexpr ModInt operator-(const ModInt rhs)const noexcept{
        return ModInt(*this)-=rhs;
    }
    inline constexpr ModInt operator*(const ModInt rhs)const noexcept{
        return ModInt(*this)*=rhs;
    }
    inline constexpr ModInt operator/(const ModInt rhs)const noexcept{
        return ModInt(*this)/=rhs;
    }
    inline constexpr ModInt operator+(const ll rhs) const noexcept{
        return ModInt(*this)+=ModInt(rhs);
    }
    inline constexpr ModInt operator-(const ll rhs)const noexcept{
        return ModInt(*this)-=ModInt(rhs);
    }
    inline constexpr ModInt operator*(const ll rhs)const noexcept{
        return ModInt(*this)*=ModInt(rhs);
    }
    inline constexpr ModInt operator/(const ll rhs)const noexcept{
        return ModInt(*this)/=ModInt(rhs);
    }

    inline constexpr ModInt &operator+=(const ModInt rhs)noexcept{
        a+=rhs.a;
        if(a>=MOD) a-=MOD;
        return *this;
    }
    inline constexpr ModInt &operator-=(const ModInt rhs)noexcept{
        if(rhs.a>a) a+=MOD;
        a-=rhs.a;
        return *this;
    }
    inline constexpr ModInt &operator*=(const ModInt rhs)noexcept{
        a=(a*rhs.a)%MOD;
        return *this;
    }
    inline constexpr ModInt &operator/=(ModInt rhs)noexcept{
        a=(a*rhs.inverse().a)%MOD;
        return *this;
    }
    inline constexpr ModInt &operator+=(const ll rhs)noexcept{
        return *this+=ModInt(rhs);
    }
    inline constexpr ModInt &operator-=(const ll rhs)noexcept{
        return *this-=ModInt(rhs);
    }
    inline constexpr ModInt &operator*=(const ll rhs)noexcept{
        return *this*=ModInt(rhs);
    }
    inline constexpr ModInt &operator/=(const ll rhs)noexcept{
        return *this/=ModInt(rhs);
    }

    inline constexpr ModInt operator=(const ll x)noexcept{
        a=(x>=0)?(x%MOD):(x%MOD+MOD);
        return *this;
    }

    inline constexpr bool operator==(const ModInt p)const noexcept{
        return a==p.a;
    }

    inline constexpr bool operator!=(const ModInt p)const noexcept{
        return a!=p.a;
    }

    inline constexpr ModInt pow(ll N) const noexcept{
        ModInt ans(1LL),p(a);
        while(N>0){
            if(bitUP(N,0)){
                ans*=p;
            }
            p*=p;
            N>>=1;
        }
        return ans;
    }
    inline constexpr ModInt inverse() const noexcept{
        return pow(MOD-2);
    }

};
inline constexpr ModInt operator+(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)+=b;
}
inline constexpr ModInt operator-(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)-=b;
}
inline constexpr ModInt operator*(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)*=b;
}
inline constexpr ModInt operator/(const ll &a,const ModInt &b)noexcept{
    return ModInt(a)/=b;
}
//cout
inline ostream &operator<<(ostream &os,const ModInt &p) {
    return os<<p.a;
}

//cin
inline istream &operator>>(istream &is,ModInt &p) {
    ll t;
    is>>t;
    p=t;
    return is;
}

struct Binominal{
    vector<ModInt> fac,finv,inv; //fac[n]:n! finv:(n!)の逆元
    int sz;
    Binominal(int n=10) :sz(1){
        if(n<=0) n=10;
        init(n);
    }
    inline void init(int n){
        fac.resize(n+1,1);
        finv.resize(n+1,1);
        inv.resize(n+1,1);
        for(int i=sz+1;i<=n;i++){
            fac[i]=fac[i-1]*i;
            inv[i]=MOD-inv[MOD%i]*(MOD/i);
            finv[i]=finv[i-1]*inv[i];
        }
        sz=n;
    }
    //nCk(n,k<=N) をO(1)で求める
    inline ModInt com(int n,int k){
        if(k==0 or k==n) return 1;
        if(n<k) return ModInt(0);
        if(n<0 || k<0) return ModInt(0);
        if(n>sz) init(n);
        return fac[n]*finv[k]*finv[n-k];
    }
    //nCk(k<=N) をO(k)　で求める 
    inline ModInt rcom(ll n,int k){
        if(n<0 || k<0 || n<k) return ModInt(0);
        if(k>sz) init(k);
        ModInt ret(1);
        for(int i=0;i<k;i++){
            ret*=n-i;
        }
        ret*=finv[k];
        return ret;
    }

    //重複組み合わせ n種類のものから重複を許してk個を選ぶ
    //〇がn個,|がk個
    inline ModInt h(int n,int k){
        return com(n+k-1,k);
    }
    //power[N+1] (power[i]=x^i)を返す
    static vector<ModInt> MakePower(ll x,int N){
        vector<ModInt> ret(N+1);
        ret[0]=1;
        for(int i=1;i<=N;i++){
            ret[i]=ret[i-1]*x;
        }
        return ret;
    }
};
vector<int> Subset(int S,bool zero=false,bool full=false){
    vector<int> ret;
    int now=(S-1)&S;
    if(full and S){
        ret.push_back(S);
    }
    do{
        ret.push_back(now);
        now=(now-1)&S;
    }while(now!=0);
    if(zero){
        ret.push_back(0);
    }
    return ret;
}

//xと差が最小の値を持つ添え字を返す
//xはソート済みを想定
//1つだけ返す
template<typename T>
inline int MinimumAbs(vector<T> &v,T x){
    assert(v.size());
    auto large=lower_bound(v.begin(),v.end(),x);
    auto small=large;
    if(large==v.begin()) return large-v.begin();
    if(large==v.end()) return v.size()-1;
    small--;
    if(abs(*small-x)>abs(*large-x)) small=large;
    return small-v.begin();
}


class modint{
    using u64=uint_fast64_t;
    static u64 &mod(){
        static u64 mod_=0;
        return mod_;
    }
public:
    u64 a;
    modint(const ll x=0):a((x>=0)?(x%mod()):(x%mod()+mod())){}
    modint operator+(const modint rhs)const{
        return modint(*this)+=rhs;
    }
    modint operator-(const modint rhs)const{
        return modint(*this)-=rhs;
    }
    modint operator*(const modint rhs)const{
        return modint(*this)*=rhs;
    }
    modint operator/(const modint rhs)const{
        return modint(*this)/=rhs;
    }
    modint &operator+=(const modint rhs){
        a+=rhs.a;
        if(a>=mod()) a-=mod();
        return *this;
    }
    modint &operator-=(const modint rhs){
        if(a<rhs.a) a+=mod();
        a-=rhs.a;
        return *this;
    }
    modint &operator*=(const modint rhs){
        a=a*rhs.a%mod();
        return *this;
    }
    modint &operator/=(const modint rhs){
        a=(a*rhs.inverse().a)%mod();
        return *this;
    }
    inline modint &operator+=(const ll rhs){
        return *this+=modint(rhs);
    }
    inline modint &operator-=(const ll rhs){
        return *this-=modint(rhs);
    }
    inline modint &operator*=(const ll rhs){
        return *this*=modint(rhs);
    }
    inline modint &operator/=(const ll rhs){
        return *this/=modint(rhs);
    }

    inline modint pow(u64 N)const{
        modint ans(1LL),p(a);
        while(N>0){
            if(bitUP(N,0)){
                ans*=p;
            }
            p*=p;
            N>>=1;
        }
        return ans;
    }
    inline modint inverse()const{
        return pow(mod()-2);
    }
    inline modint operator=(const ll x){
        a=(x>=0)?(x%mod()):(x%mod()+mod());
        return *this;
    }

    static void set_mod(const u64 x){mod()=x;}
    static u64 get_mod(){return mod();}
};
inline modint operator+(const ll a,const modint b)noexcept{
    return modint(a)+=b;
}
inline modint operator-(const ll a,const modint b)noexcept{
    return modint(a)-=b;
}
inline modint operator*(const ll a,const modint b)noexcept{
    return modint(a)*=b;
}
inline modint operator/(const ll &a,const modint &b)noexcept{
    return modint(a)/=b;
}
//cout
inline ostream &operator<<(ostream &os,const modint &p) {
    return os<<p.a;
}

//cin
inline istream &operator>>(istream &is,modint &p) {
    ll t;
    is>>t;
    p=t;
    return is;
}
template<class T>
vector<vector<T>> Binominal(int n){
    vector<vector<T>> table(n+1,vector<T>(n+1,0));
    table[0][0]=1;
    for(int i=1;i<=n;i++){
        table[i][0]=1;
        for(int j=1;j<=i;j++){
            table[i][j]=table[i-1][j-1]+table[i-1][j];
        }
    }
    return table;
};

void solve(){
    int N,M;
    cin>>N>>M;
    auto power=vmake(N,3,0);
    for(int i=0;i<N;i++){
        for(int j=0;j<3;j++) cin>>power[i][j];
    }
    using DD=double;
    vector<DD> prob(M+100);
    auto B=Binominal<ll>(M+100);
    DD zen=0;
    for(int a=0;a<=M;a++){
        for(int b=0;b<=M;b++){
            if(a+b>M) continue;
            zen+=B[M][a]*B[M-a][b];
        }
    }
    for(int i=M;i>=0;i--){
        if(i!=M) prob[i]=prob[i+1];
        for(int j=0;j+i<=M;j++){
            prob[i]+=B[M][i]*B[M-i][j]/zen;
        }
    }
    auto point=vmake(3,M+1,(DD)0);
    for(int i=0;i<3;i++){
        for(int m=0;m<=M;m++){
            DD sai=1.0;
            auto dp=vmake(3,(DD)0);
            dp[0]=1;
            int p=power[0][i]*m;
            for(int k=1;k<N;k++){
                //負ける確率を求める
                int tp=power[k][i];
                int cnt=(p+tp-1)/tp;
                DD pb=0;
                if(cnt<=M) pb=prob[cnt];
                sai*=pb;
                for(int j=2;j>=0;j--){
                    if(j<=1) dp[j+1]+=dp[j]*pb;
                    dp[j]=dp[j]*(1-pb);
                }
            }
            DD ret=0;
            ret+=sai*(-1);
            DD x=5;
            if(i==1) x=3;
            else if(i==2) x=2;
            ret+=x*(dp[0]+dp[1]+dp[2]);
            point[i][m]=ret;
        }
    }
    DD ans=-MAX;
    for(int a=0;a<=M;a++){
        for(int b=0;b<=M;b++){
            if(a+b>M) continue;
            chmax(ans,point[0][a]+point[1][b]+point[2][M-a-b]);
        }
    }
    cout<<ans<<endl;
}

};

int main(){
    BIN101::bin101();
    int T=1;
    //cin>>T;
    while(T--) BIN101::solve();
}
accuracy: 0.47368421052631576
time_ms: 10
memory_kb: 12940
final_rank: 20

code_snippet: #include<iostream>
#include<iomanip>
using namespace std;
double comb[2001];
double up[2001];
int N,M;
int A[3][2000];
double p[3][2001][2];
double dp[2000][3];
int main()
{
	cin>>N>>M;
	comb[0]=1;
	for(int i=1;i<=M;i++)
	{
		comb[i]=comb[i-1]*(M+1-i)/i;
	}
	for(int i=0;i<=M;i++)
	{
		up[i]=comb[i];
		for(int j=i;j<M;j++)up[i]=up[i]*2/3;
		for(int j=0;j<i;j++)up[i]/=3;
	}
	for(int i=M;i--;)up[i]+=up[i+1];
	for(int i=0;i<N;i++)for(int j=0;j<3;j++)cin>>A[j][i];
	for(int I=0;I<3;I++)
	{
		for(int i=0;i<=M;i++)
		{
			dp[0][0]=1;
			double all=1;
			for(int j=1;j<N;j++)
			{
				int cnt=(A[I][0]*i+A[I][j]-1)/A[I][j];
				double np=cnt<=M?up[cnt]:0;
				dp[j][2]=dp[j-1][2]*(1-np)+dp[j-1][1]*np;
				dp[j][1]=dp[j-1][1]*(1-np)+dp[j-1][0]*np;
				dp[j][0]=dp[j-1][0]*(1-np);
				all*=np;
			}
			for(int j=0;j<3;j++)p[I][i][0]+=dp[N-1][j];
			p[I][i][1]=all;
		}
	}
	double ans=-9e18;
	for(int a=0;a<=M;a++)for(int b=0;a+b<=M;b++)
	{
		int c=M-a-b;
		double now=p[0][a][0]*5+p[1][b][0]*3+p[2][c][0]*2;
		now-=p[0][a][1]+p[1][b][1]+p[2][c][1];
		if(ans<now)ans=now;
	}
	cout<<fixed<<setprecision(16)<<ans<<endl;
}
accuracy: 0.5263157894736842
time_ms: 20
memory_kb: 3604
final_rank: 18

code_snippet: #include<iostream>
#include<iomanip>
using namespace std;
long double comb[2001];
long double up[2001];
int N,M;
int A[3][2000];
long double p[3][2001][2];
long double dp[2000][3];
int main()
{
	cin>>N>>M;
	comb[0]=1;
	for(int i=1;i<=M;i++)
	{
		comb[i]=comb[i-1]*(M+1-i)/i;
	}
	for(int i=0;i<=M;i++)
	{
		up[i]=comb[i];
		for(int j=i;j<M;j++)up[i]=up[i]*2/3;
		for(int j=0;j<i;j++)up[i]/=3;
	}
	for(int i=M;i--;)up[i]+=up[i+1];
	for(int i=0;i<N;i++)for(int j=0;j<3;j++)cin>>A[j][i];
	for(int I=0;I<3;I++)
	{
		for(int i=0;i<=M;i++)
		{
			dp[0][0]=1;
			long double all=1;
			for(int j=1;j<N;j++)
			{
				int cnt=(A[I][0]*i+A[I][j]-1)/A[I][j];
				long double np=cnt<=M?up[cnt]:0;
				dp[j][2]=dp[j-1][2]*(1-np)+dp[j-1][1]*np;
				dp[j][1]=dp[j-1][1]*(1-np)+dp[j-1][0]*np;
				dp[j][0]=dp[j-1][0]*(1-np);
				all*=np;
			}
			for(int j=0;j<3;j++)p[I][i][0]+=dp[N-1][j];
			p[I][i][1]=all;
		}
	}
	long double ans=-9e18;
	for(int a=0;a<=M;a++)for(int b=0;a+b<=M;b++)
	{
		int c=M-a-b;
		long double now=p[0][a][0]*5+p[1][b][0]*3+p[2][c][0]*2;
		now-=p[0][a][1]+p[1][b][1]+p[2][c][1];
		if(ans<now)ans=now;
	}
	cout<<fixed<<setprecision(16)<<ans<<endl;
}
accuracy: 1
time_ms: 130
memory_kb: 3908
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double INF = 100;
int main(){
  cout << fixed << setprecision(20);
  int n, m;
  cin >> n >> m;
  vector<vector<int>> A(n, vector<int>(3));
  for (int i = 0; i < n; i++){
    for (int j = 0; j < 3; j++){
      cin >> A[i][j];
    }
  }
  vector<vector<double>> P(m + 1, vector<double>(m + 1, 0));
  P[0][0] = 1;
  for (int i = 0; i < m; i++){
    for (int j = 0; j <= i; j++){
      P[i + 1][j] += P[i][j] / 3 * 2;
      P[i + 1][j + 1] += P[i][j] / 3;
    }
  }
  vector<double> S(m + 2);
  S[m + 1] = 0;
  for (int i = m; i >= 0; i--){
    S[i] = S[i + 1] + P[m][i];
  }
  double ans = 0;
  vector<int> W = {5, 3, 2};
  vector<vector<double>> dp(4, vector<double>(m + 1, -INF));
  dp[0][0] = 0;
  for (int i = 0; i < 3; i++){
    vector<vector<double>> dp2(m + 1, vector<double>(4, 0));
    for (int j = 0; j <= m; j++){
      dp2[j][0] = 1;
      dp2[j][3] = 1;
    }
    for (int j = 1; j < n; j++){
    	vector<vector<double>> dp3(m + 1, vector<double>(4, 0));
      for (int k = 0; k <= m; k++){
        int c = (A[0][i] * k + A[j][i] - 1) / A[j][i];
        c = min(c, m + 1);
        double p = S[c];
        for (int l = 0; l < 3; l++){
          dp3[k][l] += dp2[k][l] * (1 - p);
          dp3[k][l + 1] += dp2[k][l] * p;
        }
        dp3[k][3] = dp2[k][3] * p;
      }
      swap(dp2, dp3);
    }
    vector<double> E(m + 1);
    for (int j = 0; j <= m; j++){
      E[j] = (dp2[j][0] + dp2[j][1] + dp2[j][2]) * W[i] - dp2[j][3];
    }
    for (int j = 0; j <= m; j++){
      for (int k = 0; k <= m - j; k++){
        dp[i + 1][j + k] = max(dp[i + 1][j + k], dp[i][j] + E[k]);
      }
    }
  }
  cout << dp[3][m] << endl;
}
accuracy: 1
time_ms: 470
memory_kb: 34676
final_rank: 15

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long long INF = 1e18;
//const ll mod = 1000000007;
ll N, M;
ll A[3][2005];
ll score[3] = {5, 3, 2};
long double calc[2005];
long double P[2005];
long double val[3][2005];
long double logFactorial[5000];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    for(int i = 1; i < 5000; i++) {
        logFactorial[i] = logFactorial[i-1] + log(i);
    }
    cin >> N >> M;
    for(int i = 0; i <= M; i++) {
        long double tmp = 0;
        tmp -= logFactorial[i];
        tmp -= logFactorial[M-i];
        tmp += logFactorial[M];
        tmp -= log(3) * M;
        tmp += log(2) * (M - i);
        P[i] = exp(tmp);
        //cerr << i << " " << P[i] << endl;
    }
    for(int i = 0; i < M; i++) {
        P[i+1] += P[i];
    }
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < 3; j++) {
            cin >> A[j][i];
        }
    }
    for(int t = 0; t < 3; t++) {
        val[t][0] = -1;
        for(int i = 1; i <= M; i++) {
            ll a = A[t][0] * i;
            for(int j = 1; j < N; j++) {
                ll num = (a - 1) / A[t][j];
                chmin(num, M);
                //cerr << t << " " << a << " " << j << " " << num << endl;
                calc[j] = P[num];
                //cerr << j << " " << calc[j] << endl;
                //cerr << num << " " << P[num] << endl;
            }
            long double sum = 0;
            long double powsum = 0;
            long double prod = 1;
            long double ALLLOSE = 1;
            for(int j = 1; j < N; j++) {
                long double win = calc[j];
                long double lose = 1 - win;
                //cerr << win << " " << lose << endl;
                prod *= win;
                sum += lose / win;
                powsum += pow(lose / win, 2);
                ALLLOSE *= lose;
            }
            long double A = (sum * sum - powsum) / 2;
            //cerr << prod << " " << ALLLOSE << endl;
            //cerr << A << " " << sum << endl;
            A += sum;
            A += 1;
            val[t][i] = A * prod * score[t] - ALLLOSE;
            //cerr << t << " " << i << " " << val[t][i] << " " << A * prod << " " << ALLLOSE << endl;
        }
    }
    long double ans = -3;
    for(int i = 0; i <= M; i++) {
        for(int j = 0; i + j <= M; j++) {
            long double tmp = val[0][i] + val[1][j] + val[2][M-i-j];
            chmax(ans, tmp);
        }
    }
    cout << fixed << setprecision(30) << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 4036
final_rank: 2

code_snippet: #pragma region Macros
// #pragma GCC optimize("O3")
// #pragma GCC target("avx2,avx")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void yes(bool t = 1) { cout << yesno[t] << endl; }
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return move(res);
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return move(res);
}

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto &e : v) cout << e << " ";
    cout << endl;
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    cout << "(" << p.fi << ", " << p.se << ")";
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
template <class A> string to_string(A v) {
    if(v.empty()) return "{}";
    string ret = "{";
    for(auto &x : v) ret += to_string(x) + ",";
    ret.back() = '}';
    return ret;
}

void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#define endl '\n'
#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
#define debug(x)
#endif
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
// ll rndll(ll n) { return uniform_int_distribution<ll>(0, n - 1)(rng); }

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#define drop(s) cout << #s << endl;
#pragma endregion

int main() {
    INT(n, m);
    n--;
    VEC(int, a, 3);
    VV(int, v, n, 3);
    vector<double> dp = {1};
    rep(i, m) {
        vector<double> nxt(si(dp) + 1);
        rep(j, si(dp)) nxt[j + 1] += dp[j] / 3, nxt[j] += dp[j] * 2 / 3;
        swap(dp, nxt);
    }
    vector<double> rui(m + 2);
    rep(i, m + 1) rui[i + 1] = rui[i] + dp[i];
    vv(double, E, m + 1, 3);
    vi point{5, 3, 2};
    rep(i, m + 1) {
        rep(j, 3) {
            int now = a[j] * i;
            vec(double, cnt, 4);
            double last = 1;
            cnt[0] = 1;
            rep(k, n) {
                int ma = ((now % v[k][j]) ? now / v[k][j] : now / v[k][j] - 1);
                double p = rui[min(m + 1, ma + 1)];
                last *= (1 - p);
                vector<double> nxt(4);
                rep(s, 4) nxt[min((int)s + 1, 3)] += cnt[s] * (1 - p), nxt[s] += cnt[s] * p;
                swap(nxt, cnt);
            }
            E[i][j] -= last;
            rep(k, 3) E[i][j] += cnt[k] * point[j];
        }
    }
    double ans = -1e15;
    rep(i, m + 1) {
        rep(j, m + 1) {
            if(i + j > m) continue;
            int k = m - i - j;
            chmax(ans, E[i][0] + E[j][1] + E[k][2]);
        }
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 230
memory_kb: 3916
final_rank: 7

code_snippet: #include <algorithm>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
using namespace std;

int main(){
  using T = long double;

  int n, m;
  cin >> n >> m;
  vector<vector<int>> D(n,vector<int>(3));
  for(int i = 0; i < n; ++i)
    for(int j = 0; j < 3; ++j)
      cin >> D[i][j];

  vector<T> P(m+1);// 
  P[0] = 1;
  for(int i = 0; i < m; ++i)
    P[0] *= 2.0/3.0;

  for(int i = 0; i < m; ++i)
    P[i+1] = P[i]/2*(m-i)/(i+1);

  for(int i = m; i > 0; --i)
    P[i-1] += P[i];

  const vector<int> pp = {5,3,2};
  
  vector<vector<T>> E(3,vector<T>(m+1));
  for(int i = 0; i < 3; ++i){
    for(int j = 0; j <= m; ++j){
      int t = D[0][i]*j;
      vector<T> p(n-1);
      T w = 1.0;
      for(int k = 1; k < n; ++k){
        int c = (t+D[k][i]-1)/D[k][i];
        p[k-1] = (c > m ? 0.0 : P[c]);// i が 0 に勝つ確率
        w *= p[k-1];
      }
      E[i][j] -= w;
      vector<T> dp(3);
      dp[0] = 1;
      for(int k = 0; k+1 < n; ++k){
        vector<T> dp_(3);
        for(int l = 0; l < 3; ++l){
          if(l+1 < 3)
            dp_[l+1] += dp[l]*p[k];
          dp_[l] += dp[l]*(1-p[k]);
        }
        swap(dp,dp_);
      }
      for(int k = 0; k < 3; ++k)// 順位 (0-indexed)
        E[i][j] += pp[i]*dp[k];
    }
  }

  const T INF = 100, EPS = 1e-8;
  vector<T> dp(m+1,-INF);
  dp[0] = 0;
  for(int i = 0; i < 3; ++i){
    vector<T> dp_(m+1,-INF);
    for(int j = 0; j <= m; ++j){
      if(dp[j] <= -INF+EPS) continue;
      for(int k = 0; k <= m; ++k){
        if(j+k > m) break;
        if(E[i][k] <= -INF+EPS) continue;
        dp_[j+k] = max<T>(dp_[j+k],dp[j]+E[i][k]);
      }
    }
    swap(dp,dp_);
  }
  assert(dp[m] >= -3.0-EPS);
  dp[m] = max<T>(dp[m],-3.0);
  cout << fixed << setprecision(12) << dp[m] << endl;
}
accuracy: 1
time_ms: 560
memory_kb: 3592
final_rank: 13