Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
prime_factorize.hpp
[詳解]
1#pragma once
2#include"../../kyopro_library/template.hpp"
3#include"../../kyopro_library/math/primality_test.hpp"
4
5/// @brief ポラードのロー法で n を素因数分解する
6/// @note O(N^(1/4))
7/// @ref https://qiita.com/t_fuki/items/7cd50de54d3c5d063b4a
8/// @ref verify: https://algo-method.com/tasks/553
10 using lll=__int128_t;
11 if(PrimalityTest(n)) return {{n,1}};
12 auto find_factor=[](auto&& find_factor, ll n)-> ll {
13 lll m=(ll)pow(n,0.125)+1;
14 auto _gcd=[](lll a, lll b) {
15 while(a) b%=a,swap(a,b);
16 return b;
17 };
18 auto _abs=[](lll x) { return x<0?-x:x; };
19 for(ll c=1; c<=n; c++) {
20 auto f=[&](lll x) { return((x%n)*(x%n)+c)%n; };
21 lll y=0,r=1,q=1,g=1,k=0,x=0,ys=0;
22 while(g==1) {
23 x=y;
24 while(k<r*3/4) y=f(y),k++;
25 while(k<r&&g==1) {
26 ys=y;
27 for(int i=0; i<min(m,r-k); i++) y=f(y), q=q*_abs(x-y)%n;
28 g=_gcd(q,n); k+=m;
29 }
30 k=r; r*=2;
31 }
32 if(g==n) {
33 g=1,y=ys;
34 while(g==1) y=f(y), g=_gcd(_abs(x-y),n);
35 }
36 if(g<n) {
37 if(PrimalityTest(g)) return g;
38 if(PrimalityTest(n/g)) return n/g;
39 return find_factor(find_factor,g);
40 }
41 }
42 return 0;
43 };
44 map<ll,ll> mp;
45 ll i=2;
46 while(i*i<=n) {
47 ll k=0;
48 while(n%i==0) n/=i, k++;
49 if(k) mp[i]=k;
50 i+=i%2+1;
51 if(i==101 && n>=(1ll<<20)) {
52 while(n>1) {
53 if(PrimalityTest(n)) mp[n]=1, n=1;
54 else {
55 ll j=find_factor(find_factor,n);
56 k=0;
57 while(n%j==0) n/=j,k++;
58 mp[j]=k;
59 }
60 }
61 }
62 }
63 if(n>1) mp[n]=1;
64 vector<pair<ll,ll>> ret;
65 for(auto p: mp) ret.push_back(p);
66 sort(ret.begin(),ret.end());
67 return ret;
68}
bool PrimalityTest(ll n)
ミラーラビン素数判定法により n が素数であるかを判定する
vector< pair< ll, ll > > PrimeFactorize(ll n)
ポラードのロー法で n を素因数分解する