ポゥ

はじめに

競技プログラミングをする際は自作のpow関数を定義すると思います.
下記コードのようにlong longで動作するpow関数を定義して呼んだ場合,出力はいくつになるでしょうか.
期待する出力は1024%10,つまり4ですが,実際の出力は1024となります.
不思議ですね.解決しましょう.

#include <iostream>

using ll = long long;
constexpr ll MOD = 10;

constexpr ll pow(ll a, ll p) {
	ll ans = 1;
	for (int i = 0; i < p; ++i) { ans *= a; ans %= MOD; }
	return ans;
}

signed main() {
	const auto val = pow(2, 10);
        std::cout << val << std::endl;
}

原因

まずは原因を探ってみましょう.
結論から言うと,呼び出し時の引数がint型となっており,
デフォルトで定義されているpow関数が呼ばれているのが原因です.
そのため,下記のように引数がlonglong型であることを明示すれば良いのですが,
競技中の焦りの中では明示するのを忘れてしまうことがよくあります.
特に,多くの場合ではlonglong型変数を引数として渡すためpow関数は正常に動作することから,
たまたま値をそのまま渡すという場合にLLを忘れず付けるという発想になることはほとんどないでしょう.

const auto val = pow(2LL, 10LL);

解決

関数の使用者側に負担をかけたくないので,pow関数自体を修正します.
方法は簡単で,int型仕様のpow関数を自作関数に置き換えるだけです.
解決してしまいました.

constexpr signed pow(signed a, signed p) { assert(false); return -1; }

おわりに

非常に簡単な内容でしたが,自分自身たまにやらかしてしまうので戒めの意味も込めて執筆しました.
一度修正(追加)するだけで二度とエラーが起こりえないのは非常に素晴らしいので,
競プロバグあるある等があれば設計単位で解決していくのもおもしろそうですね.