Skip to content

Instantly share code, notes, and snippets.

@buyoh
Last active November 6, 2018 12:07
Show Gist options
  • Save buyoh/f14582d65a8d8dad6547995c1fbd1490 to your computer and use it in GitHub Desktop.
Save buyoh/f14582d65a8d8dad6547995c1fbd1490 to your computer and use it in GitHub Desktop.
TECH PLAYで連載されている「パズルのアルゴリズム問題」を解いてみた ref: https://qiita.com/buyoh/items/86264d274ce0932a18aa
#include "bits/stdc++.h"
using namespace std;
int main() {
int N;
cin >> N;
vector<int> mat(9);
for (int i = 0; i < 9; ++i)
mat[i] = N + i;
do {
int sum = mat[0] + mat[1] + mat[2];
if (sum == mat[3] + mat[4] + mat[5] &&
sum == mat[6] + mat[7] + mat[8] &&
sum == mat[0] + mat[3] + mat[6] &&
sum == mat[1] + mat[4] + mat[7] &&
sum == mat[2] + mat[5] + mat[8] &&
sum == mat[0] + mat[4] + mat[8] &&
sum == mat[2] + mat[4] + mat[6]) {
printf("%2d%2d%2d\n", mat[0], mat[1], mat[2]);
printf("%2d%2d%2d\n", mat[3], mat[4], mat[5]);
printf("%2d%2d%2d\n", mat[6], mat[7], mat[8]);
break;
}
} while (next_permutation(mat.begin(), mat.end()));
return 0;
}
#include "bits/stdc++.h"
using namespace std;
map<array<int, 3>, int> memo; // メモ化再帰
// n: じゃんけんを行う回数
// ma: aさんがゴールに到達するまでに必要な段数
// mb: bさんがゴールに到達するまでに必要な段数
// @return: Aさんが先にゴールに到達するようなそれぞれの出す手が何通りあるか
int solve(int n, int ma, int mb) {
if (ma <= 0) return 1; // 既にゴールラインを超えているので勝ち
if (mb <= 0) return 0; // 既にゴールラインを超えているので負け
if (n <= 0) return 0; // じゃんけんしないので勝つことも無い
// メモ化再帰(キャッシュ)
array<int, 3> key = { n, ma, mb };
if (memo.count(key)) return memo[key];
int ans = 0;
ans += solve(n - 1, ma, mb)*3; // あいこのパターンは3つ
ans += solve(n - 1, ma - 1, mb) * 1; // GでAが勝つパターンは1つ
ans += solve(n - 1, ma - 2, mb) * 2; // G以外でAが勝つパターンは2つ
ans += solve(n - 1, ma, mb - 1) * 1; // GでBが勝つパターンは1つ
ans += solve(n - 1, ma, mb - 2) * 2; // G以外でBが勝つパターンは2つ
return memo[key] = ans;
}
int main() {
int n, m;
cin >> m >> n;
cout << solve(n, m, m) << endl;
return 0;
}
#include "bits/stdc++.h"
using namespace std;
// 駅の個数
const int M = 29;
// 間隔
const int D[] = {
13, 7, 10, 06, 11,
11, 5, 8, 16, 07,
11, 18, 12, 9, 14,
13, 7, 15, 12, 16,
15, 12, 9, 20, 22,
15, 12, 11, 8
};
// 円周
const int Dtotal = accumulate(D, D + M, 0);
// 人の数
int N;
// base駅に必ず1人置いて,marginずつ間隔を開けて座れるか?
bool check(int margin, int base) {
int len = 0;
int ptr = 0;
for (int i = 1; i < N; ++i) {
int x = 0;
while (x < margin) {
x += D[(base + ptr++) % M];
if (ptr >= M) return false;
}
len += x;
}
return Dtotal - len >= margin;
}
// marginずつ間隔を開けて配置できるか
bool check(int margin) {
for (int i = 0; i < M; ++i) {
if (check(margin, i)) return true;
}
return false;
}
int main() {
cin >> N;
// 二分探索
int tval = 0, fval = Dtotal;
while (fval - tval > 1) {
int v = (fval + tval) / 2;
if (check(v))
tval = v;
else
fval = v;
}
cout << tval << endl;
return 0;
}
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
int width, height;
// 幅1高さhのサイズに積み重ねて隙間なく配置するとき
// その配置が何通りあるか求める
ll calculate_col(int h) {
if (h == 0) return 1; // 選ばない,の1通り
if (h == 1) return 1; // 1つ選ぶ,の1通り
return calculate_col(h - 1) + calculate_col(h - 2);
}
// calculate x**p
inline ll my_pow(ll x, ll p) {
ll ans = 1;
for (ll i = 0; i < p; ++i)
ans *= x;
return ans;
}
int main() {
cin >> width >> height;
cout << my_pow(calculate_col(height), width);
return 0;
}
// calculate bigx *= y
function multiply(bigx, y) {
let carry = 0;
for (let i = 0; i < bigx.length; ++i) {
carry += bigx[i] * y;
bigx[i] = carry % 10000;
carry = Math.floor(carry / 10000);
}
if (carry > 0) bigx.push(carry);
return bigx;
}
function bignum_to_string(bigx) {
let str = "";
for (let i = 0; i < bigx.length-1; ++i) {
let s = "" + bigx[i];
while (s.length < 4) s = "0" + s;
str = str + s;
}
return "" + bigx[bigx.length-1] + str;
}
function fibo(n) {
let a = 1, b = 1;
while (--n)
[a, b] = [b, a+b];
return b;
}
function solve(width, height) {
const cl = fibo(height);
let ans = [1];
for (let i = 0; i < height; ++i)
multiply(ans, cl);
console.log(bignum_to_string(ans));
}
solve(10, 10);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment