Lilliput Steps

小さな一歩から着実に. 数学やプログラミングのことを書きます.

(Old) NPCA #33 : 濁流

問題文 : 濁流

きつねの曲大好きな身としては, 解かなければと思い意を決して取り組みました.
concon 好きです.

解法 :
算数, しよう.(提案)
明らかに(x, y) と(y, x) を押す順番は一緒なので, x > y なら折り返してしまいましょう.
その後, マスの斜め上半分だけに注目します. (行列で言うと上三角になっている箇所.)
たとえば, 大きさ 4 のmofbeat 板なら

①②④⑥
 ③⑤⑧
  ⑦⑨
   ⑩

この部分です.

すると, 左上方向から順番に番号がついていること気づきます. 和が小さいものの並びですネ.
そこで, f(x) : 和がx 未満でunique な番号の個数 という関数をがんばって作ります.
同じ和のグループの中で, 自分の位置はabs(x - y) / 2 + 1 番目 になります(問題文から分かります).

実装は軽いですが, なかなかおもしろい問題です.

コード :

#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long lint;

lint f(lint x)
{
	lint ret;
	lint s = x / 2;
	
	ret = s * (s - 1) / 2 * 2;
	if (x & 1) ret += s;
	
	return (ret);
}

int main()
{
	lint N, y, x;
	lint pos;
	
	scanf("%lld %lld %lld", &N, &y, &x);
	if (x < y) swap(x, y);
	
	pos = abs(x - y) / 2 + 1;
	
	if (x + y <= N + 1){
		pos += f(x + y);
	}
	else {
		lint s = N / 2;
		pos += s * (s + 1) / 2 * 2;
		if (N & 1) pos += (N + 1) / 2;
		pos += f(N + 1) - f(2 * N + 3 - x - y);
	}
	
	printf("%lld\n", pos);
	
	return (0);
}