久しぶりに素因数分解する問題が来た!!!!!!!!!!!
問題概要
正の整数 に対して、以下の操作を何回行うことができるか、その最大回数を求めよ。なお、素数 と正の整数 を用いて の形で表すことのできる整数を「素数べき」と呼ぶことにする。
- の約数であるような素数べき を一つ選ぶ +ただし、過去の操作で選んだ整数は二度用いることはできない
- を で置き換える
制約
考えたこと
とても久しぶりに、素因数分解系の問題が来た!!!
まずこの手の問題でとても大切なことは
と素因数分解したときに、 の各素因数 については完全に独立に考えて良いということがあると思う。今回でいえば単純に
- についての最大操作回数
- についての最大操作回数
- ...
- についての最大操作回数
をそれぞれ求めて、合計すれば OK!!!なお、素因数分解は で実現できる。
N = pe の場合
というわけで問題は、 自身が素数べきである場合、すなわち、
の場合を考えることに帰着された!!!
- のとき、 の 1 回のみ
- のとき、 をやると、 になってもうダメなので 1 回だけ
- のとき、 の 2 回ができる
- のとき、重複なしだと の 2 回しかできない
- のとき、 の 3 回ができる
- ...
という風になる。よって、以下の Greedy で求めることができる。
- を順に試して行って
- やれるところまでやる
なお、 という制約から、 は大体 くらいなので、 はどんなに大きくても 40 くらい。よって、愚直にやっても間に合う。
#include <bits/stdc++.h> using namespace std; // 素因数分解 vector<pair<long long, long long> > prime_factorize(long long n) { vector<pair<long long, long long> > res; for (long long p = 2; p * p <= n; ++p) { if (n % p != 0) continue; int num = 0; while (n % p == 0) { ++num; n /= p; } res.push_back(make_pair(p, num)); } if (n != 1) res.push_back(make_pair(n, 1)); return res; } int main() { long long N; cin >> N; auto pf = prime_factorize(N); long long res = 0; for (auto p : pf) { long long e = p.second; long long tmp = 0, cur = 1; while (e >= cur) e -= cur++, ++tmp; res += tmp; } cout << res << endl; }