A는 miller_rabin 소수성
miller_rabin 소수성 테스트는 많은 수의 소수가 있는지 여부를 확인하는 데 사용되는 알고리즘입니다. miller_rabin이 확률 알고리즘이며, 이는 시험의 수가 S, 다음 에러의 확률이 4 ^이다 설정 오류의 특정 확률을 가지고 - (S)
알고리즘의 이론적 근거 :
- 페르마 정리 A는 임의의 양의 정수 (1≤ a≤ N-1)이고, n은 다음 홀수 소수하는 ^ (N-1) ≡ 1 개조 N 인 경우.
- N이 홀수 소수 인 경우 * R 형체 -3,4- 2와 같이 N-1 발현, R은 홀수, A는이고 n은 임의의 정수 비교적 프라임 후 ^ RN ≡ 1 개조 N 또는 j의 (0 ≤ j≤ S-1 j∈Z)은 ^ (2jr) ≡ -1 개조 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;
}
둘, 폴라드-RHO 인수 분해
폴라드-RHO 분해 시간 복잡도는 (N ^ 1/4 O )
큰 정수 n에 대해, 우리는 임의의 수의 걸릴 N X 품질 계수의 확률이 작이며 우리는 두 숫자 X1 및 그 차이 (n)의 계수가되도록 X2를 취할 경우, 확률은 X1 및 X2가 GCD되도록 취해진 경우 ((X1-X2)을 크게 할 것 > n)이 1보다 높은 확률. 이 폴라드-의 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;
}