// Errichto
// Div1-Easy
public class BearCavalry {
public int countAssignments(int[] warriors, int[] horses) {
final int mod = 1000 * 1000 * 1000 + 7;
int n = warriors.length;
long ans = 0;
for(int assign = 0; assign < n; ++assign) {
int strenghtLimit = warriors[0] * horses[assign];
int h2[] = new int[n - 1];
for(int i = 0; i < assign; ++i) h2[i] = horses[i];
for(int i = assign + 1; i < n; ++i) h2[i-1] = horses[i];
int h2Pointer = 0;
long m = 1;
for(int i = n - 1; i >= 1; --i) {
while(h2Pointer < h2.length && warriors[i] * h2[h2Pointer] < strenghtLimit)
++h2Pointer;
m = m * (h2Pointer - (n-1 - i)) % mod;
}
ans = (ans + m) % mod;
}
return (int) ans;
}
}
// Div1-Med
public class BearPermutations {
public int countPermutations(int N, int S, int mod) {
long bin[][] = new long[N+1][N+1];
for(int i = 0; i <= N; ++i) {
bin[i][0] = 1;
for(int j = 1; j <= i; ++j)
bin[i][j] = (bin[i-1][j-1] + bin[i-1][j]) % mod;
}
// dp[n][where][s]
long dp[][][] = new long[N+1][N+1][S+1];
long left[][] = new long[N+1][S+1];
dp[1][1][0] = 1;
for(int n = 1; n <= N; ++n) {
// where the smallest/biggest number goes
for(int where = 1; where <= n; ++where) {
if(where == 1 || where == n) {
for(int where0 = 1; where0 <= n - 1; ++where0)
for(int s = 0; s <= S; ++s) {
dp[n][where][s] += dp[n-1][where0][s];
dp[n][where][s] %= mod;
}
}
else {
int n1 = where - 1;
int n2 = n - where;
for(int s1 = 0; s1 <= S; ++s1)
for(int s2 = 0; s2 <= S - s1; ++s2) {
dp[n][where][s1+s2] += left[n1][s1] * left[n2][s2] % mod * bin[n1+n2][n1];
dp[n][where][s1+s2] %= mod;
}
}
for(int s = 0; s+where <= S; ++s) {
left[n][s+where] += dp[n][where][s];
left[n][s+where] %= mod;
}
}
}
long ans = 0;
for(int where = 1; where <= N; ++where)
for(int s = 0; s <= S; ++s)
ans += dp[N][where][s];
ans %= mod;
return (int) ans;
}
}
// Div1-Hard
public class BearGirls {
public double expectedValue(int[] A, int[] T, int cost) {
int n = 0;
for(int i = 0; i < T.length; ++i)
n += T[i];
int[] t = new int[n];
int iii = 0;
for(int i = 0; i < A.length; ++i)
for(int j = 0; j < T[i]; ++j)
t[iii++] = A[i] + j;
// f(k, r) is the expected value of the r-th biggest number from k randomly selected values from the input
// f(k,r) = p * f(k+1,r+1) + (1-p) * f(k+1,r)
// where p = r/(k+1)
double[] smart = new double[n+1], stupid = new double[n+1];
for(int i = 1; i <= n; ++i)
smart[i] = stupid[i] = t[i-1];
for(int k = n-1; k >= 1; --k) {
double nxt = 0;
for(int i = 1; i <= k + 1; ++i)
nxt += smart[i] / (k + 1);
for(int i = 1; i <= k; ++i) {
double p = i / (k + 1.);
stupid[i] = p * stupid[i+1] + (1-p) * stupid[i];
smart
[i
] = Math.
max(nxt
-cost, stupid
[i
]); }
}
return smart[1] - cost;
}
}