PCK 2018 Final (AOJ 0401) Playing With Stones
解法
grundy数を考える。白石、黒石がともに0個のときこれ以上の遷移ができず、必敗であることが分かる。また、石は等しい個数同士を交換するか取り除くしかないため、最終的に必ずこの状態になる。よって、再帰的にgrundy数を求めることができる。これをメモ化すれば制約が小さいので十分高速である。
実装
提出コード - https://onlinejudge.u-aizu.ac.jp/status/users/mhrb_minase/submissions/1/0401/judge/3748519/C++14
#include<iostream> #include<algorithm> #include<set> using namespace std; int grundy[201][101]; int dfs(int w, int b){ if(grundy[w][b] >= 0){ return grundy[w][b]; } set<int> st; if(w > 0){ st.insert(dfs(w - 1, b)); } if(b > 0){ st.insert(dfs(w + 1, b - 1)); } for(int i = 1 ; i <= b && i <= w ; ++i){ st.insert(dfs(w, b - i)); } int res = 0; while(st.count(res)){ ++res; } return grundy[w][b] = res; } int main(){ cin.tie(0); ios::sync_with_stdio(false); fill(grundy[0], grundy[201], -1); grundy[0][0] = 0; int n; cin >> n; int v = 0; for(int i = 0 ; i < n ; ++i){ int w, b; cin >> w >> b; v ^= dfs(w, b); } if(v == 0){ cout << 1 << endl; }else{ cout << 0 << endl; } return 0; }
PCK 2018 Final (AOJ 0400) Maze and Items
解法
0-9, A-J, a-j, S, Tの高々32頂点間の距離を幅優先探索で求める。このとき、A-J及びa-jは通り抜けてはならないことにする。0-9に0-9、A-Jに10-19、a-jに20-29、Sに30、Tに31の番号を割り当て、グラフを作る。数字を持っているかいないかの各状態ごとにダイクストラ法で全頂点対の最短距離を求める。その後、どの順番で数字を回収するかを全探索する。
実装
提出コード - https://onlinejudge.u-aizu.ac.jp/status/users/mhrb_minase/submissions/1/0400/judge/3743802/C++14
#include<iostream> #include<vector> #include<algorithm> #include<queue> using namespace std; using lint = long long; using P = pair<int, int>; using LLP = pair<long long, long long>; const long long LLINF = 1LL << 61; const int dx4[] = {1, 0, -1, 0}, dy4[] = {0, 1, 0, -1}; template<typename T> bool chmax(T &a, T b){ if(a < b){ a = b; return true; } return false; } template<typename T> bool chmin(T &a, T b){ if(b < a){ a = b; return true; } return false; } struct node{ int id; lint cost; bool operator<(const node& rhs) const { return cost > rhs.cost; } }; int w, h; string row[1000]; lint s[10][10]; int px[32], py[32]; lint dis[32][32]; lint cost[1 << 10][32][32]; bool check(int y, int x){ return 0 <= y && y < h && 0 <= x && x < w && row[y][x] != '#'; } int main(){ cin.tie(0); ios::sync_with_stdio(false); cin >> w >> h; fill(px, px + 32, -1); fill(py, py + 32, -1); fill(dis[0], dis[32], LLINF); for(int i = 0 ; i < (1 << 10) ; ++i){ fill(cost[i][0], cost[i][32], LLINF); } for(int i = 0 ; i < h ; ++i){ cin >> row[i]; for(int j = 0 ; j < w ; ++j){ if('0' <= row[i][j] && row[i][j] <= '9'){ px[row[i][j] - '0'] = j; py[row[i][j] - '0'] = i; }else if('A' <= row[i][j] && row[i][j] <= 'J'){ px[row[i][j] - 'A' + 10] = j; py[row[i][j] - 'A' + 10] = i; }else if('a' <= row[i][j] && row[i][j] <= 'j'){ px[row[i][j] - 'a' + 20] = j; py[row[i][j] - 'a' + 20] = i; }else if(row[i][j] == 'S'){ px[30] = j; py[30] = i; }else if(row[i][j] == 'T'){ px[31] = j; py[31] = i; } } } for(int i = 0 ; i < 10 ; ++i){ for(int j = 0 ; j < 10 ; ++j){ cin >> s[i][j]; } } for(int i = 0 ; i < 32 ; ++i){ if(px[i] < 0){ continue; } lint tmpDis[1000][1000]; fill(tmpDis[0], tmpDis[h], LLINF); queue< pair<P, lint> > que; que.push({{py[i], px[i]}, 0LL}); tmpDis[py[i]][px[i]] = 0LL; while(!que.empty()){ auto now = que.front(); que.pop(); if(tmpDis[now.first.first][now.first.second] < now.second){ continue; } for(int j = 0 ; j < 4 ; ++j){ int ny = now.first.first + dy4[j], nx = now.first.second + dx4[j]; if(!check(ny, nx)){ continue; }else if(chmin(tmpDis[ny][nx], now.second + 1LL) && (row[ny][nx] == '.' || row[ny][nx] == 'S' || row[ny][nx] == 'T' || ('0' <= row[ny][nx] && row[ny][nx] <= '9'))){ que.push({{ny, nx}, now.second + 1LL}); } } } for(int j = 0 ; j < 32 ; ++j){ if(px[j] < 0){ continue; } chmin(dis[i][j], tmpDis[py[j]][px[j]]); } } for(int i = 0 ; i < (1 << 10) ; ++i){ for(int j = 0 ; j < 32 ; ++j){ if(px[j] < 0 || (j < 10 && !(i >> j & 1))){ continue; } priority_queue<node> que; que.push({j, 0LL}); cost[i][j][j] = 0LL; while(!que.empty()){ node now = que.top(); que.pop(); if(cost[i][j][now.id] < now.cost){ continue; } for(int k = 0 ; k < 10 ; ++k){ if(dis[now.id][k] >= LLINF || now.id == k){ continue; } if(chmin(cost[i][j][k], now.cost + dis[now.id][k])){ que.push({k, now.cost + dis[now.id][k]}); } } for(int k = 10 ; k < 20 ; ++k){ if(dis[now.id][k] >= LLINF || now.id == k || i >> (k - 10) & 1){ continue; } if(chmin(cost[i][j][k], now.cost + dis[now.id][k])){ que.push({k, now.cost + dis[now.id][k]}); } } for(int k = 20 ; k < 30 ; ++k){ if(dis[now.id][k] >= LLINF || now.id == k || !(i >> (k - 20) & 1)){ continue; } if(chmin(cost[i][j][k], now.cost + dis[now.id][k])){ que.push({k, now.cost + dis[now.id][k]}); } } for(int k = 30 ; k < 32 ; ++k){ if(dis[now.id][k] >= LLINF || now.id == k){ continue; } if(chmin(cost[i][j][k], now.cost + dis[now.id][k])){ que.push({k, now.cost + dis[now.id][k]}); } } } } } LLP ans = {LLINF, LLINF}; vector<int> v; for(int i = 0 ; i < 10 ; ++i){ v.emplace_back(i); } do{ if(cost[0][30][v[0]] >= LLINF || cost[(1 << 10) - 1][v[9]][31] >= LLINF){ continue; } LLP tmp = {cost[0][30][v[0]] + cost[(1 << 10) - 1][v[9]][31], 0LL}; bool flag = true; int state = 1 << v[0]; for(int i = 0 ; i < 9 ; ++i){ if(cost[state][v[i]][v[i + 1]] >= LLINF){ flag = false; break; } tmp.first += cost[state][v[i]][v[i + 1]]; tmp.second -= s[v[i]][v[i + 1]]; state |= (1 << v[i + 1]); } if(flag){ chmin(ans, tmp); } }while(next_permutation(v.begin(), v.end())); if(ans.first < LLINF){ cout << ans.first << " " << -ans.second << endl; }else{ cout << -1 << endl; } return 0; }
ICPC2019 国内予選 参加記
ICPC2019 国内予選に参加しました。nicklawさん、NOSSさんと私のチームで4完41位、学内1位で予選突破しました。
チームメイトの参加記
やったこと
A問題は縦方向の和のmaxなので私が秒で実装し、通しました。Bをnicklawさんに書いてもらっている間に、私がC、NOSSさんがDを考察していました。
Cを生やした(つもりになっていましたが、誤読でした・・・)のでDの概要をNOSSさんに聞いて、しばらく考察していました。するとNOSSさんが「dpでは?」と言い、何やら遷移を生やし始めたので信じることにしました(実装の方針などを私も少し考えました)。
BがWAったので私がCを書き始めたのですが、この時点で誤読に気づいてめちゃくちゃ焦りました。間もなくBが修正できたようなので実装をしてもらうことにして、Cを解き直していました。nicklawさんがBを通したので、Cの解き直しを2人で行いました。
解法は、各分銅に対して使わない、左に乗せる、右に乗せるを全探索して、(右に乗せる重さの和 - 左に乗せる重さの和)を列挙します。これで全てのaを作れれば0、そうでないなら作れなかったもののうち1つに対して、a - (右に乗せる重さ - 左に乗せる重さ)を追加する分銅の重さの候補として列挙します。これらの候補及び既存の分銅を用いて全てのaを作れるか判定する、といった感じでした。
これを実装すると無限にサンプルが合わないのでプリントデバッグに入り、NOSSさんがDの実装を始めました。後でわかったのですが、合わなかった原因は、追加する分銅を左に乗せるか右に乗せるかを考慮するのを忘れていたことでした。
この間2人でCとDを書いてはバグらせ書いては無限時間実行され書いてはバグらせを繰り返し、その間nicklawさんも含めてバグ探しに専念しました。2完が見えて焦り始めていたところでCとDを立て続けに通せました。Cは先述したところの修正をしたら通りました。Dは計算量的にやばかったのですが、コンパイルオプション-O3をつけたら爆速で実行されて通すことができました。
この時点で残り1時間ほどでしたが、Eは実装が重そうなので飛ばし、Fを3人で考えました(何も生えませんでした)。
反省
- 早とちりしないで紙で実装をちゃんと詰めること
- コンパイル時点での最適化は大事
- ワンマンプレイをしない
感想(という名のポエム)
まずはなんと言っても、目標にしていたアジア大会出場を曲がりなりにも達成できてよかったです。自分自身としても嬉しいですし、M1の先輩の最後のICPCで国内予選を突破できたことが嬉しかったです。また、おそらくチームのうち誰一人欠けても4完はできなかったと思います(チームメイトもすごかったし、自分が抜けても危うかったと自負してる(ほんまか?))し、チームプレイをちゃんとできたのかなというところが最高でした。小中高通じてこれと言って何かをやった経験があまりなかった自分にとって、大学で競技プログラミングに出会い、打ち込めるようになったこと、それを仲間とともにできる環境があったこと、ICPCに出られたこと、全てが夢のように思え、奇跡であると感じています。このめぐり合わせに感謝しつつ、アジア大会に向けて日々過ごしていきたいなと思います。
AGC033 A Darker and Darker
問題ページ - A - Darker and Darker
概要
行列のマス目が与えられる。各マスは白、または黒のいずれかに塗られている。全てのマスが黒色になるまで、以下の操作を繰り返す。- 白いマスであって、黒いマスと辺を共有するマスを黒くする。
この操作が何回行われるか求めよ。
制約
- 黒いマスが1つ以上存在する
解法
まず、初めにある黒いマスは1個だけであるという場合を考える。1回の操作で黒いマスと辺を共有するマスが全て黒くなるということは、そのマスが黒くなるのに必要な操作回数は、黒マスを始点としたグリッドグラフの最短路の長さと同じである。よって、全体で行われる操作回数は、黒マスから一番遠い頂点までの最短路の長さと同じと言える。これは幅優先探索で求めることができる。では、黒いマスが2個以上ある場合はどうだろうか。この場合も似たような手順で求めることができる。単一始点の最短経路問題では、初めにキューに始点を入れて探索を始める。同様に、黒いマスが2個以上ある場合は予め全ての黒いマスをキューに入れてから探索を始める。キューの先頭から順にコストを並べたとき、単調非減少であればよいため、この方法で答えを求めることができる。提出コード
https://atcoder.jp/contests/agc033/submissions/5298324#include<bits/stdc++.h> using namespace std; const int INF = (1 << 30) - 1; /* マス(y,x)と辺を共有するマスは、(y,x+1), (y+1,x), (y,x-1), (y-1,x) の4つであるため、このような配列を用いて効率的に探索できる */ const int dy4[] = {0, 1, 0, -1}, dx4[] = {1, 0, -1, 0}; int main(){ // 入力 int h, w; cin >> h >> w; vector<string> a(h); for(int i = 0 ; i < h ; ++i){ cin >> a[i]; } // 幅優先探索 queue< pair< pair<int, int>, int> > que; // {{y座標, x座標}, コスト} vector< vector<int> > cost(h, vector<int>(w, INF)); // 最小コスト // 黒いマスをキューに入れる for(int i = 0 ; i < h ; ++i){ for(int j = 0 ; j < w ; ++j){ if(a[i][j] == '#'){ que.push({{i, j}, 0}); cost[i][j] = 0; } } } // 最小コストの更新が止まるまで探索 while(!que.empty()){ auto now = que.front(); que.pop(); if(cost[now.first.first][now.first.second] < now.second){ continue; } cost[now.first.first][now.first.second] = now.second; for(int i = 0 ; i < 4 ; ++i){ int ny = now.first.first + dy4[i], nx = now.first.second + dx4[i]; if(0 <= ny && ny < h && 0 <= nx && nx < w && cost[ny][nx] > now.second + 1){ cost[ny][nx] = now.second + 1; que.push({{ny, nx}, now.second + 1}); } } } // 最小コストの最大値を求める int ans = 0; for(int i = 0 ; i < h ; ++i){ for(int j = 0 ; j < w ; ++j){ ans = max(ans, cost[i][j]); } } cout << ans << endl; return 0; }
AtCoder青になりました
コンテスト初参加から1年で青くなることができました! pic.twitter.com/fND6dnbB5b
— まほろば (@mhrb_minase) 2019年4月20日
先日行われたTenka1 Programmer Contest2019でレートが1657になり、青色に到達しました(なお執筆時点のレートは1642な模様)。300-600-800-800のセットの1完早解き黄パフォで青になっており、多少後味は悪かったですが、ともかく色が変わって嬉しかったです。ここでは、n番煎じながらやったこと等をまとめたいと思います。
~灰
大学の競技プログラミング部に入部しました。AtCoder Programming Guide for beginners(APG4b)で、先輩方に教えていただきつつ競プロに使う言語であるC++の基礎を学びました。その後、コンテストに1回参加しました。
学んだアルゴリズム等
この頃はif文とfor文が書ける程度で、単純な演算や繰り返し処理ができた程度だと思います。~茶
競技プログラミング部での活動として、バーチャルコンテストをやっていました。問題セットはABCの過去問でした。また、AtCoder Beginners Selectionを埋めたり、AIZU ONLINE JUDGEのLessonやLibraryをちまちまとやったりもしました。
学んだアルゴリズム等
- 多重for文による全探索
- 約数列挙
- 素数判定
- 配列上の二分探索(下3つを使うようになるのはもう少し後かも)
~緑
狂ったようにABCのA,Bを埋めていました。いわゆる虚無埋めですね。ただ、このおかげでB問題までを解くスピードが上がり、後ろの問題にかけられる時間が増えたと思います。また、実装にどう落とし込むのかというのが分かってきたところで、300点問題を通せるようになってきました。
学んだアルゴリズム等
- std::sort
- std::next_permutation
- 最大公約数(ユークリッドの互除法での実装)
- 最小公倍数
- 素数列挙(エラトステネスの篩)
- 再帰関数を用いたあれこれ(例えばこういうの ※ネタバレ注意 を再帰で計算したり)
- 累積和
- いもす法
- 幅優先探索
- 深さ優先探索
- 余りを取る問題の足し算、引き算、掛け算
- 繰り返し二乗法
~水
まず、C問題を確実に時間内に解けるように、過去問のC問題を埋めていました。C問題がほぼ確実に解けるようになった頃には、自然と400点のD問題を自力で解けるようになっていました。先述した競技プログラミング部内でのバーチャルコンテストや、部内で競うように精進していたことなどの成果が出たと思います。そして、300点以下を高速で通すマンになりました(流石に青以上の方々と比べられるとアですが)。これにより大失敗を回避できました(実質的な力がついていなくてよくなさそうですね)。このあたりから、競技プログラミング部内のバーチャルコンテストはAOJ Arenaを用いて行われるようになりました。
学んだアルゴリズム等
- bit全探索
- 二分探索
- union-find木
- 素数modの逆元
- combinationの計算法
- グラフの最短経路問題(ダイクストラ法、ベルマンフォード法、ワーシャルフロイド法)
- 最小全域木(コンテスト中にこれを使った記憶はありません)
- ナップサック問題等の易しめの典型DP
- メモ化再帰
- 2次元以上の累積和・いもす法
- 半分全列挙
~青
300点以下を爆速で通すマンになりました(流石に黄色以上の方々と比べられ(ry。必然的に400点くらいの問題もそこそこのスピード(30分前後?)で通せるようになり、また、ABC+ARC相当の企業コンテストやAGCが続いたこともあり、レート上昇の要因は早解きがかなりのウェイトを占めています(考察力をつけなさ~い)。とは言っても、500,600点程度の問題は3割くらいは通しているはずなので、早解きにも限界があると思われます。400点~600点くらいの得点帯の過去問を解くようにした成果だと思います(にしては突破率が低いような・・・?)。最近では~800点くらいまででコンテスト中に見た問題は復習するようにしています。コンテストに月1回出るか出ないかくらいの頻度でCodeforcesに手を出しています。yukicoderもちょこっとかじりました。
学んだアルゴリズム等
- 座標圧縮
- セグメント木(これが想定解の問題にはコンテストではほとんど出会っていません)
まとめ
†低得点帯の早解き力†を鍛えましょう(大失敗が少なくなるので)ABC124参加記
先日行われたAtCoder Beginner Contest 124に参加した。今回は、全てPython3で解いた。
A問題
問題ページ
解法は、愚直にシミュレーションをした。コードは以下の通り。
a, b = map(int, input().split()) ans = 0 for i in range(2): if a > b: ans = ans + a a = a - 1 else: ans = ans + b b = b - 1 print(ans)
B問題
問題ページ
これは、西から順に見ていき、今まで見た中での高さの最大値を保持しておくことで各山についてで判定できる(制約が小さいので2重ループでも間に合うと思われる)。初期値を以下にしておけば、一番西側も同様に処理できる。コードは以下の通り。
n = int(input()) h = list(map(int, input().split())) ans = 0 maxi = -1 for i in range(n): if maxi <= h[i]: ans = ans + 1 maxi = max(maxi, h[i]) print(ans)
C問題
問題ページ
色の種類が2種類で、隣り合った色が異ならなければならない。よって、最終状態は奇数番目が色0で偶数番目が色1、またはその逆しかありえない。そこで、奇数番目、偶数番目それぞれについて色1の個数を数えておくことで、色を変えなければならない個数を求めることができる。コードは以下の通り。
s = input() s = list(map(int, s)) n = len(s) cnt = [0] * 2 for i in range(n): m = i % 2 if s[i] == 1: cnt[m] = cnt[m] + 1 ans = min((n // 2 + n % 2 - cnt[0]) + cnt[1], cnt[0] + (n // 2 - cnt[1])) print(ans)
D問題
問題ページ
回の操作での最適解は、0のみが連続する部分を選ぶパターンである。回の操作での最適解も、そのような部分を連続した個選ぶのが最適である。実装方針は、まず、与えられたデータから、左から順に連続する同じ数字の個数の配列を作っておく。例えば、入力が110011110ならば、2, 2, 4, 1という具合にする。この配列の累積和の配列を作り、これをとすると、の最大値が答えとなる。かかは、にあたるのが0か1かによる。よって、偶奇と先頭で場合分けをすれば良い。コードは以下の通りである。max(i - k * 2, 0)等は、配列外参照の防止や、配列長が未満のケースに対応するためである(ちょうど回ではなく回以下なのでこの書き方でおk)。
n, k = map(int, input().split()) s = input() s = list(map(int, s)) v = [] cnt = 1 for i in range(n - 1): if s[i] == s[i + 1]: cnt = cnt + 1 else: v.append(cnt) cnt = 1 v.append(cnt) m = len(v) sum = [0] * (m + 1) for i in range(1, m + 1): sum[i] = sum[i - 1] + v[i - 1] ans = 0 for i in range(m + 1): if s[0] == 0: if i % 2 == 0: ans = max(ans, sum[i] - sum[max(i - k * 2 - 1, 0)]) else: ans = max(ans, sum[i] - sum[max(i - k * 2, 0)]) else: if i % 2 == 0: ans = max(ans, sum[i] - sum[max(i - k * 2, 0)]) else: ans = max(ans, sum[i] - sum[max(i - k * 2 - 1, 0)]) print(ans)
感想
pythonの記法に慣れてきた。後から+=と-=があることを知ったので、次回以降はこう書けると思う。
y_n_ucpc合宿参加記
合宿
始まりはいつも突然に
2月6日21:07、横浜国立大学競技プログラミング部(YNUCPC)Slackに、山梨大学競技プログラミング部(YUCPC)から合同合宿の誘いが来てる旨を伝えるメッセージが投下された。その後なんやかんやあり、22:22の時点で既に合宿用のワークスペースが立ち上げられていた。この間僅か1時間15分である。合宿地は箱根、日程は3月23日・24日の1泊2日であった。参加者
阪大のゆきりんさんは、xueleiさんが呼んだら来てくださったそうです。1日目
現地に13:00集合・・・の、はずであったが、9人中4人しか来ていなかった。結局13:20頃に8人揃ったと思う(1人は元々遅れる予定だった)。バチャがこどふぉった。#y_n_ucpc春合宿2019
— ぷにぷに エンジニア見習い (@puni_kyopro) 2019年3月23日
TLEer大量発生
集合時刻過ぎて、4/9人しか集まらない合宿とは
— まほろば (@mhrb_minase) 2019年3月23日
山梨組、合宿に出発です!
— 山梨大学競技プログラミング部 (@yucpclub) 2019年3月23日
中の人は起床TLEしたので、特急課金しました#y_n_ucpc春合宿2019 pic.twitter.com/WDUy80v5jr
バチャ
https://onlinejudge.u-aizu.ac.jp/beta/room.html#YNUYUCPC2019/info - コンテストページ1日目のバチャはA~Hの8問でチーム戦だった。NOSSさんがセットしてくださった。残りの7人を2,2,3人のチームに分けた。私はニクローさんとMaskさんと組んだ。私のチームの流れは大体↓みたいな感じだったと思う。
- チームメイトがA,Bを解く
- Cの考察が終わっていたので書いた
- その間にニクローさんがDの考察を終えて、Cを通した直後に実装を始めていたのでEを考察した
- C→D→Eの3問をチーム全体で19分ほどで通した。完璧
- Fは3人で考えたが、私が考察を生やしたので書く。バグる。申し訳ないm(_ _)m。なんとか通した
- その時点でチームメイトのGの考察が仕上がっていた
- 実装がうまくいっていなかったが、概要を聞いたら私のライブラリを貼ると良さそうだったので、貼った。通った
- 残り3分時点で、暖めていたHのTLE解を祈りながら投げたらWAだった。虚無
夜
夕食情報#y_n_ucpc春合宿2019
— 横浜国大 競技プログラミング部 (@ynu_cpc) 2019年3月23日
夕食情報です pic.twitter.com/9v69HT1GA8
この時点でもう一人が合流した。
部屋で畳にパソコンを置いてAGCオンサイトをやった。暖まった。外ではしゃいでいた別の団体がほどよい雑音を作り出していたことに感謝。
AGCの準備を始める人々(結託はしません)#y_n_ucpc春合宿2019 pic.twitter.com/ui1HywEGXr
— まほろば (@mhrb_minase) 2019年3月23日
風呂は旅館の浴場(温泉!)を使った。
2日目
役場の放送に叩き起こされた。夢の中で考察が生えかけていただけに残念である。バチャ
https://not-522.appspot.com/contest/5115126982115328 - コンテストページ2日目のバチャも8問でチーム戦だった。commyさんがセットしてくださった。3,3,2人のチームに分けた。私はプニプニさんと組んだ。流れは
- プニプニさんがAを通す
- その間私はCを考察していて、Aが通った直後に書き始めて、通した
- その間にプニプニさんがBの考察を済ませ、すぐに実装に入り、通した。私のPCを使っていたが、私が提出する問題を間違えるなどして5分のいらんペナを喰らった。謝罪
- 私はその後すぐにDを書き、通した
- E,Fが生えそうで詰めきれない
- Gは明らかに†破滅†
- Hは通せそうだったので書いた。通した
- Eの考察を詰め、プニプニさんに実装をしていただいた
- 実装の間、私がFの考察を詰めた。Eが通った直後に書き始めた。通した
- Gの部分点を取りに行った
その後
観光タイムに突入。この日はABCがあったので、小田原に行く組と大涌谷に行く組に別れて行動した。私はゆきりんさん、ToMさん、ニクローさん、xueleiさんとともに大涌谷に行った。3月だというのに雪が積もっており、気温の低さ故の蒸気のせいか、大涌谷の煙がいつもより多く見えた。黒たまごを買ったのは初めてだったかもしれない。— まほろば (@mhrb_minase) 2019年3月24日
箱根登りました #y_n_ucpc春合宿2019 pic.twitter.com/uGVw3ICE2W
— ニクロー (@nicklaw296) 2019年3月24日
さいごに
とても楽しかったです。調和級数や巨大数のmodなどの競プロ的な知見も得られ、観光パートも充実していました。よい2日間でした。企画・運営してくださった方々、参加者の皆様にこの場を借りて感謝します。本当にありがとうございました。また、よろしければ↓もどうぞ
- https://kusozakokyopro.wordpress.com/2019/03/24/ynuyucpc%EF%BC%9F/ - ゆきりんさんの参加記
- https://xuelei.hatenadiary.com/entry/2019/03/28/020821 - xueleiさんの参加記
- https://ynucpc.github.io/blog/2019/03/27/y_n_ucpc2019spr/ - 横国競プロ部公式記事(ニクローさんが書いてくださりました)
- #y_n_ucpc春合宿2019 - ツイッターハッシュタグ。ここに合宿の様子がまとまっています