結果

問題 No.58 イカサマなサイコロ
ユーザー not_522not_522
提出日時 2015-07-19 18:34:50
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 4 ms / 5,000 ms
コード長 5,366 bytes
コンパイル時間 1,822 ms
コンパイル使用メモリ 167,020 KB
実行使用メモリ 4,380 KB
最終ジャッジ日時 2023-09-22 19:18:39
合計ジャッジ時間 2,521 ms
ジャッジサーバーID
(参考情報)
judge14 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,380 KB
testcase_01 AC 4 ms
4,376 KB
testcase_02 AC 2 ms
4,376 KB
testcase_03 AC 2 ms
4,376 KB
testcase_04 AC 3 ms
4,380 KB
testcase_05 AC 3 ms
4,376 KB
testcase_06 AC 4 ms
4,376 KB
testcase_07 AC 1 ms
4,380 KB
testcase_08 AC 1 ms
4,380 KB
testcase_09 AC 4 ms
4,380 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

using namespace std;

namespace arithmetic {
  template<typename T> class Addition {
  public:
    template<typename V> T operator+(const V& v) const {
      T res(static_cast<const T&>(*this));
      return res += static_cast<T>(v);
    }
  };

  template<typename T> class Subtraction {
  public:
    template<typename V> T operator-(const V& v) const {
      T res(static_cast<const T&>(*this));
      return res -= static_cast<T>(v);
    }
  };

  template<typename T> class Multiplication {
  public:
    template<typename V> T operator*(const V& v) const {
      T res(static_cast<const T&>(*this));
      return res *= static_cast<T>(v);
    }
  };

  template<typename T> class Division {
  public:
    template<typename V> T operator/(const V& v) const {
      T res(static_cast<const T&>(*this));
      return res /= static_cast<T>(v);
    }
  };

  template<typename T> class Modulus {
  public:
    template<typename V> T operator%(const V& v) const {
      T res(static_cast<const T&>(*this));
      return res %= static_cast<T>(v);
    }
  };
}

template<typename T> class IndivisibleArithmetic : public arithmetic::Addition<T>, public arithmetic::Subtraction<T>, public arithmetic::Multiplication<T> {};

template<typename T> class Arithmetic : public IndivisibleArithmetic<T>, public arithmetic::Division<T> {};

template<typename T> class Vector : public arithmetic::Addition<Vector<T>>, public arithmetic::Subtraction<Vector<T>> {
protected:
  vector<T> val;

public:
  Vector(int n) : val(n, 0) {}

  T& operator[](int n) {
    return val[n];
  }
	
	Vector operator+=(const Vector& v) {
    for (int i = 0; i < size(); ++i) val[i] += v[i];
		return *this;
	}
	
	Vector operator-=(const Vector& v) {
    for (int i = 0; i < size(); ++i) val[i] -= v[i];
		return *this;
	}

  T operator*(const Vector& v) const {
    return inner_product(val.begin(), val.end(), const_cast<Vector&>(v).begin(), T(0));
  }

  int size() const {
    return val.size();
  }

  typename vector<T>::const_iterator begin() const {
    return val.begin();
  }

  typename vector<T>::const_iterator end() const {
    return val.end();
  }
};

template<typename T> class Matrix : public arithmetic::Addition<Matrix<T>>, public arithmetic::Subtraction<Matrix<T>> {
protected:
  vector<Vector<T>> val;
  
public:
  Matrix(int n, int m) : val(n, Vector<T>(m)) {}

  Vector<T>& operator[](int n) {
    return val[n];
  }
	
	Matrix operator+=(const Matrix& m) {
    for (int i = 0; i < (int)val.size(); ++i) val[i] += m[i];
		return *this;
	}
	
	Matrix operator-=(const Matrix& m) {
    for (int i = 0; i < (int)val.size(); ++i) val[i] -= m[i];
		return *this;
	}

  Matrix operator*=(const Matrix& _m) {
    Matrix &m = const_cast<Matrix&>(_m);
    Matrix res(size(), m[0].size());
    for (int i = 0; i < size(); ++i) {
      for (int j = 0; j < m.size(); ++j) {
        for (int k = 0; k < m[0].size(); ++k) {
          res[i][k] += val[i][j] * m[j][k]; 
        }
      }
    }
    return *this = res;
  }
  
  Matrix operator*(const Matrix& m) const {
    Matrix res = *this;
    return res *= m;
  }
  
  Vector<T> operator*(const Vector<T>& v) {
    Vector<T> res(size());
    for (int i = 0; i < size(); ++i) res[i] += val[i] * v;
    return res;
  }

  int size() const {
    return val.size();
  }
};

template<typename T> class SquareMatrix : public Matrix<T>, public arithmetic::Division<SquareMatrix<T>> {
public:
  SquareMatrix(int n) : Matrix<T>(n, n) {}

  SquareMatrix(const Matrix<T>& m) : Matrix<T>(m) {}

	SquareMatrix operator/=(const SquareMatrix& m) {
		return *this *= m.inverse();
	}

  SquareMatrix identity() const {
    SquareMatrix res(this->size());
    for (int i = 0; i < this->size(); ++i) res[i][i] = 1;
    return res;
  }

  SquareMatrix inverse() const {
    int n = this->size();
    SquareMatrix mat = *this;
    SquareMatrix inv = identity();
    for (int i = 0; i < n; ++i) {
      int p = i;
      for (int j = i + 1; j < n; ++j) {
        if (abs(mat[j][i]) > abs(mat[p][i])) p = j;
      }
      swap(mat[i], mat[p]);
      swap(inv[i], inv[p]);
      for (int j = i + 1; j < n; ++j) mat[i][j] /= mat[i][i];
      for (int j = 0; j < n; ++j) inv[i][j] /= mat[i][i];
      mat[i][i] = 1;
      for (int j = 0; j < n; ++j) {
        if (i == j) continue;
        T a = mat[j][i];
        for (int k = 0; k < n; ++k) {
          mat[j][k] -= a * mat[i][k];
          inv[j][k] -= a * inv[i][k];
        }
      }
    }
    return inv;
  }
};

template<typename T> T pow(T& m, long long n) {
  if (n == 0) {
    return m.identity();
  } else if (n < 0) {
    return m.identity() / pow(m, -n);
  }
  T mm = pow(m, n / 2);
  mm *= mm;
  if (n % 2) mm *= m;
  return mm;
}

int main() {
  int n, k;
  cin >> n >> k;
  const int mx = 6 * n;
  SquareMatrix<double> m1(mx + 1), m2(mx + 1);
  for (int i = 0; i < mx; ++i) {
    for (int j = 1; j <= 6; ++j) {
      if (i + j <= mx) m1[i + j][i] = 1.0 / 6;
    }
    for (int j = 4; j <= 6; ++j) {
      if (i + j <= mx) m2[i + j][i] = 2.0 / 6;
    }
  }
  Vector<double> v(mx + 1);
  v[0] = 1;
  auto taro = (Matrix<double>)pow(m1, n - k) * (Matrix<double>)pow(m2, k) * v;
  auto jiro = pow(m1, n) * v;
  double res = 0;
  for (int i = 0; i <= mx; ++i) {
    for (int j = 0; j < i; ++j) res += taro[i] * jiro[j];
  }
  cout << fixed << setprecision(15) << res << endl;
}
0