miller_rabin素数判定+Pollard-rho素因子分解
作者:互联网
一、miller_rabin素数判定
miller_rabin是一种素性测试算法,用来判断一个大数是否是一个质数。miller_rabin是一种随机算法,它有一定概率出错,设测试次数为s,那么出错的概率是 4^(−s)
算法的理论基础:
- Fermat定理:若a是任意正整数(1≤ a≤ n−1),n是奇素数,则 a^(n-1) ≡ 1 mod n。
- 如果n是一个奇素数,将n−1表示成2^s*r 的形式,r是奇数,a与n是互素的任何随机整数,那么a^r ≡ 1 mod n,或者对某个j (0 ≤ j≤ s−1, j∈Z) 等式a^(2jr) ≡ −1 mod n 成立。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int times = 20;
int number = 0;
map<ll, int>m;
ll Random(ll n) ///生成[0,n]的随机数
{
return ((double)rand()/RAND_MAX*n+0.5);
}
ll q_mul(ll a,ll b,ll mod) ///快速乘计算 (a*b) % mod
{
ll ans=0;
while(b)
{
if(b&1)
{
b--;
ans=(ans+a)%mod;
}
b/=2;
a=(a+a)%mod;
}
return ans;
}
ll q_pow(ll a,ll b,ll mod) ///快速幂计算 (a^b) % mod
{
ll ans=1;
while(b)
{
if(b&1)
ans=q_mul(ans,a,mod);
b/=2;
a=q_mul(a,a,mod);
}
return ans;
}
bool witness(ll a,ll n )
///miller_rabin算法的主体
///用检验算子a来检验n是不是素数
{
ll temp=n-1;
int j=0;
while(temp%2==0)
{
temp/=2;
j++;
}
///将n-1拆分为a^r*s
ll x=q_pow(a,temp,n ); ///得到a^r mod n
if(x==1||x==n-1)
return true; ///余数为1则为素数
while(j--) ///否则试验条件2看是否有满足的 j
{
x=q_mul(x,x,n);
if(x==n-1)
return true;
}
return false;
}
bool miller_rabin(ll n)
///检验n是否是素数
{
if(n==2)
return true;
if(n<2||n%2==0)
return false; ///如果是2则是素数,如果<2或者是>2的偶数则不是素数
for(int i=1; i<=times; i++) ///做times次随机检验
{
ll a=Random(n-2)+1; ///得到随机检验算子 a
if(!witness(a,n)) ///用a检验n是否是素数
return false;
}
return true;
}
int main( )
{
ll tar;
while(cin>>tar)
{
if(miller_rabin(tar)) ///检验tar是不是素数
cout<<"Yes, Prime!"<<endl;
else
cout<<"No, not prime."<<endl;
}
return 0;
}
二、Pollard-rho素因子分解
Pollard-rho素因子分解的时间复杂度是:O(n^1/4)
对于一个大整数n,我们取任意一个数x是n的质因数的几率很小,如果取两个数x1以及x2使得它们的差是n的因数,那么几率就提高了,如果取x1以及x2使得gcd((x1−x2),n)>1的概率就更高了。这就是Pollard-Rho算法的主要思想。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 105;
ll x[maxn], ans;
queue<ll> aria;
ll multi(ll a, ll b, ll p) //快速乘
{
ll ans = 0;
while(b)
{
if(b & 1LL)
ans = (ans+a)%p;
a = (a+a)%p;
b >>= 1;
}
return ans;
}
ll qpow(ll a, ll b, ll p)
{
ll ans = 1;
while(b)
{
if(b & 1LL)
ans = multi(ans, a, p);
a = multi(a, a, p);
b >>= 1;
}
return ans;
}
bool miller_rabin(ll n)
{
if(n == 2)
return true;
int s = 20, i, t = 0;
ll u = n-1;
while(!(u&1))
{
t++;
u >>= 1;
}
while(s--)
{
ll a = rand()%(n-2)+2;
x[0] = qpow(a, u, n);
for(i = 1; i <= t; i++)
{
x[i] = multi(x[i-1], x[i-1], n);
if(x[i] == 1 && x[i-1] != 1 && x[i-1] != n-1)
return false;
}
if(x[t] != 1)
return false;
}
return true;
}
ll gcd(ll a, ll b)
{
if(b == 0)
return a;
else
return gcd(b, a%b);
}
ll Pollard_Rho(ll n, int c)
{
ll i = 1, k = 2, x = rand()%(n-1)+1, y = x;
while(1)
{
i++;
x = (multi(x, x, n)+c)%n;
ll p = gcd((y-x+n)%n, n);
if(p != 1 && p != n)
return p;
if(y == x)
return n;
if(i == k)
{
y = x;
k <<= 1;
}
}
}
void calc(ll n, int c)
{
if(n == 1)
return;
if(miller_rabin(n))
{
aria.push(n);
return;
}
ll p = n, k = c;
while(p >= n)
{
p = Pollard_Rho(p, c--);
}
calc(p, k);
calc(n/p, k);
}
int main()
{
ll n;
while(~scanf("%lld", &n))
{
calc(n, 107);
cout << aria.front();
aria.pop();
while(!aria.empty())
{
cout << "*" << aria.front();
aria.pop();
}
cout << endl;
}
return 0;
}
爱吃老谈酸菜的DV
发布了317 篇原创文章 · 获赞 105 · 访问量 2万+
私信
关注
标签:return,miller,ll,Pollard,while,rho,ans,mod 来源: https://blog.csdn.net/weixin_43460224/article/details/104443160