Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
factors.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2
3/// @brief エラトステネスの篩を利用した高速な素因数分解・約数列挙(Osa_k 法)
4/// @ref https://osak.jp/diary/diary_201310.html#20131017
5/// @ref https://qiita.com/drken/items/3beb679e54266f20ab63
6struct Factors {
7 /// @brief 前計算
8 /// @note O(n log(log(n)))
9 Factors(int n) {
10 mx=n;
11 min_factor=vector<int>(mx+1);
12 is_prime=vector<int>(mx+1,true); is_prime[0]=is_prime[1]=false;
13 divisors=vector<vector<int>>(mx+1);
14 prime_factors=vector<vector<pair<int,int>>>(mx+1);
15
16 for(int i=2; i<=mx; i++) if(is_prime[i]) {
17 min_factor[i]=i;
18 for(int j=2*i; j<=mx; j+=i) {
19 is_prime[j]=false;
20 if(min_factor[j]==0) min_factor[j]=i;
21 }
22 }
23 }
24
25 /// @brief n を素因数分解する
26 /// @note O(log(n))
27 vector<pair<int,int>> get_prime_factors(int n) {
28 if(prime_factors[n].size()==0) {
29 int x=n;
30 while(x>1) {
31 int p=min_factor[x];
32 int cnt=0;
33 while(x%p==0) {
34 x/=p;
35 cnt++;
36 }
37 prime_factors[n].push_back({p,cnt});
38 }
39 }
40 return prime_factors[n];
41 }
42
43 /// @brief n の約数を返す
44 /// @note O(d(n))
45 vector<int> get_divisors(int n) {
46 if(divisors[n].size()==0) {
47 vector<pair<int,int>> pf=get_prime_factors(n);
48 int sz=pf.size();
49 auto dfs=[&](auto&& dfs, int i, int x)-> void {
50 if(i==sz) {
51 divisors[n].push_back(x);
52 return;
53 }
54 auto[p,cnt]=pf[i];
55 for(int j=0; j<=cnt; j++) {
56 dfs(dfs,i+1,x);
57 x*=p;
58 }
59 };
60 dfs(dfs,0,1);
61 sort(divisors[n].begin(),divisors[n].end());
62 }
63 return divisors[n];
64 }
65
66private:
67 int mx;
68 vector<int> min_factor,is_prime;
69 vector<vector<int>> divisors;
70 vector<vector<pair<int,int>>> prime_factors;
71};
エラトステネスの篩を利用した高速な素因数分解・約数列挙(Osa_k 法) https://osak.jp/diary/diary_201310.html#20131017 https://qiita....
Definition factors.hpp:6
Factors(int n)
前計算
Definition factors.hpp:9
vector< int > get_divisors(int n)
n の約数を返す
Definition factors.hpp:45
vector< pair< int, int > > get_prime_factors(int n)
n を素因数分解する
Definition factors.hpp:27