結果
| 問題 |
No.463 魔法使いのすごろく🎲
|
| コンテスト | |
| ユーザー |
tanzaku
|
| 提出日時 | 2016-12-11 03:27:56 |
| 言語 | Java (openjdk 23) |
| 結果 |
AC
|
| 実行時間 | 204 ms / 2,000 ms |
| コード長 | 3,115 bytes |
| コンパイル時間 | 2,596 ms |
| コンパイル使用メモリ | 80,520 KB |
| 実行使用メモリ | 56,868 KB |
| 最終ジャッジ日時 | 2024-11-29 15:46:01 |
| 合計ジャッジ時間 | 10,625 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 36 |
ソースコード
import java.util.*;
public class Main {
static final Random random = new Random(0);
public static void main(String[] args) {
try (final Scanner in = new Scanner(System.in)) {
int n = in.nextInt();
int m = in.nextInt();
double[] c = new double[n];
if (!(n >= 2 && n <= 100)) throw new RuntimeException();
if (!(m >= 1 && m < n)) throw new RuntimeException();
for (int i = 1; i < n - 1; i++) {
c[i] = in.nextDouble();
// c[i] = random.nextInt(1000000000 + 1);
if (!(c[i] >= 0 && c[i] <= 1e9)) throw new RuntimeException();
}
double[][] A = new double[n-1][n-1];
double[][] C = new double[n-1][1];
for (int i = 0; i < n - 1; i++) {
for (int j = 1; j <= m; j++) {
int t = i + j;
if (t == n - 1) continue;
if (t >= n) t = n - 2 - (t - n);
A[i][t] -= 1.0 / m;
}
A[i][i] += 1;
C[i][0] = c[i];
}
double[][] E0 = mulmat(inverse(A), C);
double[] ans = new double[n];
for (int i = n - 1; i >= 0; i--) {
if (i + m >= n - 1) {
ans[i] = 0;
continue;
}
double jump = Double.POSITIVE_INFINITY;
double e = 0;
for (int j = 1; j <= m; j++) {
e += (ans[i+j] + c[i+j]) / m;
jump = Math.min(jump, E0[i+j][0]);
}
ans[i] = Math.min(e, jump);
}
// dump(c);
// dump(A);
// dump(inverse(A));
// dump(E0);
// dump(ans);
System.out.printf("%.10f\n", ans[0]);
}
}
static void dump(Object... o) {
System.err.println(Arrays.deepToString(o));
}
static <T> void swapRow(T[] ary, int i, int j) {
final T x = ary[i];
ary[i] = ary[j];
ary[j] = x;
}
static boolean inverseProcess(double[][] tmp) {
final int n = tmp.length;
for(int i = 0; i < n; i++) {
int r = i;
for(int j = i + 1; j < n; j++) {
if(Math.abs(tmp[r][i]) < Math.abs(tmp[j][i])) {
r = j;
}
}
if(i != r) {
swapRow(tmp, i, r);
}
if(Math.abs(tmp[i][i]) <= 1e-10) {
throw new RuntimeException();
}
for(int j = tmp[i].length - 1; j >= i; j--) {
tmp[i][j] /= tmp[i][i];
}
for(int j = 0; j < n; j++) if(i != j) {
for(int k = tmp[j].length - 1; k >= i; k--) {
tmp[j][k] -= tmp[j][i] * tmp[i][k];
}
}
}
return true;
}
// 逆行列を求める
static double[][] inverse(double[][] m) {
final int n = m.length;
assert(n != 0 && m[0].length == n);
final double[][] tmp = new double[n][2*n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
tmp[i][j] = m[i][j];
}
tmp[i][i + n] = 1;
}
inverseProcess(tmp);
final double[][] ret = new double[n][n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
ret[i][j] = tmp[i][j + n];
}
}
return ret;
}
// a [n,v] * b [v,m] => c[n,m]
static double[][] mulmat(double[][] a, double[][] b) {
assert(a[0].length == b.length);
final int n = a.length;
final int v = b.length;
final int m = b[0].length;
double[][] res = new double[n][m];
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
for(int k = 0; k < v; k++)
res[i][j] += a[i][k] * b[k][j];
return res;
}
}
tanzaku