Int64之內Rabin-Miller強僞素數測試和Pollard 因數分解的算法實現html
選取隨機數\(a\) 隨機數\(b\),檢查\(gcd(a - b, n)\)是否大於1,若大於1則\(a - b\)是\(n\)的一個因數算法
實現1:floyd判環測試
利用多項式\(f(x)\)迭代出\({x_0, x_1, \dots, x_k}\)spa
設定\(x = y = x_0\)的初始值,選用多項式進行迭代,每次:\(x = f(x)\), \(y = f(f(y))\),即:\(x = x_k, y = x_{2k}\)當\(x == y\)時出現循環code
設\(x = y = 2\),\(f(n) = n^2 + a\)htm
typedef long long ll; ll mul_mod(ll a, ll b, ll m){ ll ans = 0, exp = a; while(a >= m) a -= m; while(b){ if(b & 1){ ans += exp; while(ans >= m) ans -= m; } exp += exp; while(exp >= m) exp -= m; b >>= 1; } return ans; } ll pollard_rho(ll n, int a){ ll x = 2, y = 2, d = 1; while(d == 1){ x = mul_mod(x, x, n) + a; y = mul_mod(y, y, n) + a; y = mul_mod(y, y, n) + a; d = __gcd((x >= y ? x - y : y - x), n); } if(d == n) return pollard_rho(n, a + 1); return d; }
實現2: brent判環(更高效)get
不一樣於floyd每次計算\(x_k, x_{2k}\)進行判斷,brent每次只計算\(x_k\),當k是2的方冪時,\(y = x_k\),每次計算\(d = gcd(x_k - y, n)\)class
typedef long long ll; ll mul_mod(ll a, ll b, ll m){ ll ans = 0, exp = a; while(a >= m) a -= m; while(b){ if(b & 1){ ans += exp; while(ans >= m) ans -= m; } exp += exp; while(exp >= m) exp -= m; b >>= 1; } return ans; } ll pollard_rho(ll n, int a){ ll x = 2, y = 2, d = 1, k = 0, i = 1; while(d == 1){ ++k; x = mul_mod(x, x, n) + a; d = __gcd(x >= y ? x - y : y - x, n); if(k == i){ y = x; i <<= 1; } } if(d == n) return pollard_rho(n, a + 1); return d; }