文系プログラマーのプログラミング備忘録

Java、競プロ、数学などについて書いてます

Triangular Relationship [AtCoder Beginner Contest 108 C]

atcoder.jp


私にとってはかなり難しい問題でした。よって、何段階かに分けて理解します。



剰余の式を理解する

まず、以下の式変形を見てください。


・(a+b) % K = (a+c) % K
・b % K = c % K


以前も何かの問題で見た気がしますね。a=5, b=4, c=8, k=4 のときの、この式変形を、図で表してみます。


・aaaa/abbb/b
・aaaa/accc/cccc/c


つまり、K で割ったときの余りが等しいという事実は、左右の共通部分である a ではなく、左右で異なっている部分である b,c にのみ依存する、よって、両辺から a を引いても余りが等しいという事実は変わらない、という意味なんでしょう。


数学的に論理的に、ではなく、直感的に感覚的にしか理解できていませんが、とりあえず先に進みます。



a,b,c のうちの1つがKの倍数であるとき


a+b, b+c, a+c が全て K の倍数になるような a,b,c とは、いったいどのようなものなんでしょうか。


a,b,c のいずれかがもともと K の倍数であった場合を考えてみます。仮に a だとすると、a%K=0 です。


a%K=0 となるような a に足し合わせて K の倍数となるような b を考えます。このとき、b も同様に b%K=0 で、K の倍数である必要があります。6 に足して 6の倍数 になるような数は、やはり 6 の倍数以外にはないんですね。同様に、c も c%K=0 である必要があります。


となれば、条件を満たす a,b,c の組み合わせとして、


・a%K = b%K = c%K = 0


となる a,b,c が考えられます。


このような a,b,c のうち、a の個数は「1~N のうち K で割った余りが 0 になる数」の個数です。
これを仮に x とします。a,b,c は重複してもよいので、このような a,b,c の組み合わせの個数は x^3 となります。



a,b,c のうちの1つがKの倍数でないとき

仮に、a+b が 6 の倍数になるような a, b の組み合わせのうち、a も b も 6 の倍数でない場合を考えてみます。
以下のようなものが考えられます。


・1, 5
・2, 4
・3, 3


これを一般化すると、a%6 + b%6 = 6 となるような a,b だけが、a+b が 6 になり得ることがわかります。
では、これを今回の問題に当てはめてみます。


a,b,c の組み合わせは、a+b, b+c, a+c が全て K の倍数でなければいけません。すなわち、


・(a+b)%K=0 && (b+c)%K=0 && (a+c)%K=0


です。これを冒頭に紹介した式変形であれやこれやすると、


・a%K = b%K = c%K(式1)


が求まります。さらに、先ほど 6 の倍数を例に挙げて説明した a%6 + b%6 = 6 を使って、


・a%K + b%K = K
・b%K + c%K = K
・a%K + c%K = K(式2)


が得られます。式1と式2で連立方程式を立てて計算すると、


・a%K = b%K = c%K = K/2


が求まります。ここまでくればあと一息です。


a の個数は「1~N のうち K で割った余りが K/2 になる数」の個数です。これを仮に y とします。
a,b,c は重複してもよいので、このような a,b,c の組み合わせの個数は y^3 となります。
ただし y は K/2 が整数、すなわち K が偶数のとき以外は 0 となるので、注意が必要です。


最後に、前の章で求めた x^3と y^3 を足して、答えになります。


void solve () {

	int n = nextInt(), k = nextInt();
	long ans = 0L;

	//xを求める
	long x = 0;
	for (int i=1; i<=n; i++) {
		if (i%k == 0) x++;
	}

	//yを求める
	long y = 0;
	if (k%2 == 0) {
		for (int i=1; i<=n; i++) {
			if (i%k == k/2) y++;
		}
	}

	out.println(x*x*x + y*y*y);

}


これだけ解説を書いて、一応は理解できましたけど……この問題がもし本番で出題されていたら、間違いなく解けなかったでしょうね。