結果
問題 | No.214 素数サイコロと合成数サイコロ (3-Medium) |
ユーザー | mayoko_ |
提出日時 | 2015-05-23 15:32:48 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 1,483 ms / 3,000 ms |
コード長 | 5,466 bytes |
コンパイル時間 | 1,500 ms |
コンパイル使用メモリ | 171,556 KB |
実行使用メモリ | 43,488 KB |
最終ジャッジ日時 | 2024-07-06 06:20:26 |
合計ジャッジ時間 | 6,846 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1,483 ms
43,488 KB |
testcase_01 | AC | 1,123 ms
40,676 KB |
testcase_02 | AC | 1,060 ms
43,488 KB |
ソースコード
#include <bits/stdc++.h> #define rep(i, n) for (int (i) = 0; (i) < (int)(n); (i)++) const int dx[] = {1, 0, -1, 0}; const int dy[] = {0, 1, 0, -1}; using namespace std; typedef long long ll; typedef vector<int> vi; typedef vector<ll> vll; typedef pair<int, int> pii; const int a[] = {2,3,5,7,11,13}; const int b[] = {4,6,8,9,10,12}; typedef vector<ll> vec; typedef vector<vec> matrix; const ll MOD = 1e9+7; //matrix mul(const matrix& A, const matrix& B) { // int n = A.size(); // int m = B[0].size(); // int k = A[0].size(); // matrix ret(n, vec(m)); // for (int i = 0; i < n; i++) { // for (int j = 0; j < m; j++) { // for (int l = 0; l < k; l++) { // (ret[i][j] += A[i][l] * B[l][j]) %= MOD; // } // } // } // return ret; //} // //// kitamasa専用でおねがいします //matrix kitamasaMul(const matrix& A, const matrix& B) { // int n = A.size(); // assert(n == 1); // int m = B[0].size(); // matrix ret(n, vec(m)); // ret[0][0] = A[0][m-1]*B[m-1][0] % MOD; // for (int i = 1; i < m; i++) { // ret[0][i] = (A[0][i-1] + A[0][m-1]*B[m-1][i]) % MOD; // } // return ret; //} // //// Aのm乗を求める //// Aの形は一番下だけ任意の整数で良くて残りの行はA[i][i+1]のみ1 //matrix kitamasa(const matrix& A, ll m) { // int n = A.size(); // matrix B = A; // matrix u(1, vec(n)); // u[0][0] = 1; // matrix a(1, vec(n)); // while (m) { // if (m&1) { // u = mul(u, B); // } // for (int i = 0; i < n; i++) a[0][i] = B[0][i]; // a = mul(a, B); // for (int i = 0; i < n; i++) B[0][i] = a[0][i]; // for (int i = 1; i < n; i++) { // a = kitamasaMul(a, A); // for (int j = 0; j < n; j++) { // B[i][j] = a[0][j]; // } // } // m /= 2; // } // matrix ret(n, vec(n)); // for (int i = 0; i < n; i++) ret[0][i] = u[0][i]; // for (int i = 1; i < n; i++) { // u = kitamasaMul(u, A); // for (int j = 0; j < n; j++) { // ret[i][j] = u[0][j]; // } // } // return ret; //} matrix mul(const matrix& A, const matrix& B, matrix& ret) { int n = A.size(); int m = B[0].size(); int k = A[0].size(); for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) ret[i][j] = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { for (int l = 0; l < k; l++) { (ret[i][j] += A[i][l] * B[l][j]) %= MOD; } } } return ret; } // kitamasa専用でおねがいします matrix kitamasaMul(const matrix& A, const matrix& B, matrix& ret) { int n = A.size(); assert(n == 1); int m = B[0].size(); ret[0][0] = A[0][m-1]*B[m-1][0] % MOD; for (int i = 1; i < m; i++) { ret[0][i] = (A[0][i-1] + A[0][m-1]*B[m-1][i]) % MOD; } return ret; } // Aのm乗を求める // Aの形は一番下だけ任意の整数で良くて残りの行はA[i][i+1]のみ1 matrix kitamasa(const matrix& A, ll m) { int n = A.size(); matrix B = A; matrix u(1, vec(n)); u[0][0] = 1; matrix a(1, vec(n)); matrix tmp(1, vec(n)); while (m) { if (m&1) { u = mul(u, B, tmp); } for (int i = 0; i < n; i++) a[0][i] = B[0][i]; a = mul(a, B, tmp); for (int i = 0; i < n; i++) B[0][i] = a[0][i]; for (int i = 1; i < n; i++) { a = kitamasaMul(a, A, tmp); for (int j = 0; j < n; j++) { B[i][j] = a[0][j]; } } m /= 2; } matrix ret(n, vec(n)); for (int i = 0; i < n; i++) ret[0][i] = u[0][i]; for (int i = 1; i < n; i++) { u = kitamasaMul(u, A, tmp); for (int j = 0; j < n; j++) { ret[i][j] = u[0][j]; } } return ret; } const int MAXP = 55, MAXC = 55; int P, C; ll N; ll memo[MAXP][6][MAXP*15]; ll memo1[MAXP][6][MAXP*15]; ll mm[MAXP*30]; int main() { cin.tie(0); ios::sync_with_stdio(false); cin >> N >> P >> C; // 素数 memo[0][0][0] = 1; for (int i = 0; i < P; i++) { for (int j = 0; j < 6; j++) { for (int s = 0; s <= 13*P; s++) { if (memo[i][j][s] == 0) continue; for (int k = j; k < 6; k++) { (memo[i+1][k][s+a[k]] += memo[i][j][s]) %= MOD; } } } } // 合成数 memo1[0][0][0] = 1; for (int i = 0; i < C; i++) { for (int j = 0; j < 6; j++) { for (int s = 0; s <= 12*C; s++) { if (memo1[i][j][s] == 0) continue; for (int k = j; k < 6; k++) { (memo1[i+1][k][s+b[k]] += memo1[i][j][s]) %= MOD; } } } } for (int i = 0; i < P*15+1; i++) for (int j = 0; j < C*15+1; j++) { ll sum1 = 0, sum2 = 0; for (int k = 0; k < 6; k++) sum1 += memo[P][k][i]; for (int k = 0; k < 6; k++) sum2 += memo1[C][k][j]; (mm[i+j] += sum1*sum2) %= MOD; } int tmp = P*13+C*12; matrix A(tmp, vec(tmp)); for (int i = 0; i < tmp-1; i++) { A[i][i+1] = 1; } for (int i = 1; i <= tmp; i++) { A[tmp-1][tmp-i] = mm[i]; } A = kitamasa(A, N); ll ans = 0; for (int i = 0; i < tmp; i++) { (ans += A[tmp-1][i]) %= MOD; } cout << ans << endl; return 0; }