Contents
最大公約数
ユークリッドの互除法を用いて求めます。
#define ll long long // Greatest Common Divisor (最大公約数) ll gcd(ll a, ll b) { // Eucledean algorithm while (a) { if (a < b) { std::swap(a, b); } a %= b; } return b; }
※C++17以降はstd::gcdを用いることができます。C++14でも、GCCを使用している場合は__gcdを使用することができます。
AtCoderのC++はC++17になり、std::gcdが使えるようになりました。
最小公倍数
ab = gcd(a,b) * lcm(a,b)
⇔ lcm(a,b) = ab / gcd(a,b)
割り算を先に行ったほうが安全です。(オーバーフロー対策)
// Least Common Multiple ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }
※C++17以降はstd::lcmを用いることができます。
素数判定
2, 3以降の素数は6で割ったときの余りが1または5、という特性を活かすと少しだけ高速化できます。
定数倍でしか早くならないですが…
bool is_prime(const unsigned n) { if (n % 2 == 0 || n % 3 == 0) { if (n == 2 || n == 3) { return true; } return false; } if (n == 1) { return false; } for (unsigned i = 5; i * i <= n; i += 6) { if (n % i == 0 || n % (i + 2) == 0) { return false; } } return true; }
エラトステネスの篩を使用すれば候補を絞る事ができますが、n > 10^8くらいにならないと効果が得られないらしいです。
競技プログラミング界隈では、かえって実行速度は落ちると思います。
素因数分解
素因数である可能性のある数をforで回してひたすら求めます。
ここでは簡単のためにやりませんが、 2, 3, 5, 7, …と2以外は奇数を数えたほうが少し高速化されます。
// prime factorization (素因数分解) // key: value of prime factor // value: number of prime factor std::map<ll, ll> prime_factorization(ll n) { std::map<ll, ll> prime_factors; for (ll i = 2; i * i <= n; i++) { while (n % i == 0) { prime_factors[i]++; n /= i; } } if (n != 1) prime_factors[n] = 1; return prime_factors; }
使い方
std::mapはstd::pair<const key, value>のコンテナで実装されています。
auto factors = prime_factorization(n); for (auto it = factors.begin(); it != factors.end(); it++) { std::cout << it->first << " " << it->second << std::endl; }
約数の個数
auto factors = prime_factorization(n); ll num_divisor = 1; for (auto it = factors.begin(); it != factors.end(); it++) { num_divisor *= it->second + 1; }
関連問題
- Factorization (ABC110)
約数の列挙
using ll = long long; using ld = long double; // 約数リスト vector<ll> get_divisors(const ll n) { vector<ll> divs; for (ll i = 1; i * i <= n; i++) { if (n % i == 0) { divs.push_back(i); if (i != n / i) { divs.push_back(n / i); } } } // 必要に応じてソート // sort(divs.begin(), divs.end()); return divs; }
コードは下記ページを参考に作成しました。
- 約数を高速で列挙するコード(Python) – Qiita
関連問題
- Partition (ABC112)