This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/math/binary_gcd.hpp"2 数の最大公約数を求める. 一般的な Euclid の互除法による実装と異なり,非再帰かつ除算が 2 で割るものしか登場しないので bit shift で済み,約 3 から 4 倍程度高速である.
どれも理解及び証明は容易で,原理は実際にソースコードを見るのがわかりやすい. 特に $x, y$ が共に奇数ならば $x - y$ は偶数であるから効率的に計算することが可能である.
#pragma once
template <typename T> T binary_gcd(T x_, T y_) {
unsigned long long x = x_ < 0 ? -x_ : x_, y = y_ < 0 ? -y_ : y_;
if (!x or !y) return x + y;
int n = __builtin_ctzll(x), m = __builtin_ctzll(y);
x >>= n, y >>= m;
while (x != y) {
if (x > y)
x = (x - y) >> __builtin_ctzll(x - y);
else
y = (y - x) >> __builtin_ctzll(y - x);
}
return x << (n > m ? m : n);
}#line 2 "src/math/binary_gcd.hpp"
template <typename T> T binary_gcd(T x_, T y_) {
unsigned long long x = x_ < 0 ? -x_ : x_, y = y_ < 0 ? -y_ : y_;
if (!x or !y) return x + y;
int n = __builtin_ctzll(x), m = __builtin_ctzll(y);
x >>= n, y >>= m;
while (x != y) {
if (x > y)
x = (x - y) >> __builtin_ctzll(x - y);
else
y = (y - x) >> __builtin_ctzll(y - x);
}
return x << (n > m ? m : n);
}