Miller-Rabin素数判定法是典型的大数素性测试算法。
- 利用欧拉筛生成1e7个素数(即从2开始的前10000000个素数)
int prime[MAXN];
bool vis[MAXN];
int cnt = 0;
void Euler_prime(int n)
{
for (int i = 2; i <= n; ++i)
{
if (!vis[i])
{
prime[cnt++] = i; vis[i] = true;
}//vis[i]置为true或不置true都可以
for (int j = 0; j < cnt; ++j)
{
if (i * prime[j] > n)//判断是否越界
break;
vis[i * prime[j]] = true;//筛数
if (i % prime[j] == 0)//时间复杂度为O(n)的关键!
break;
}
}
}
2.编写快速积和快速幂算法
int Quick_Multiply(int a, int b, int c) //快速积
{
long long ans = 0, res = a;
while (b)
{
if (b & 1)
ans = (ans + res) % c;
res = (res + res) % c;
b >>= 1;
}
return (int)ans;
}
int Quick_Power(int a, int b, int c) //快速幂
{
int ans = 1, res = a;
while (b)
{
if (b & 1)
ans = Quick_Multiply(ans, res, c);
res = Quick_Multiply(res, res, c);
b >>= 1;
}
return ans;
}
3.Miller-Rabin素数判定算法
bool Miller_Rabin(int n) //判断素数
{
int i, j, k;
int s = 0, q = n - 1;
if (n == 2) return true; //2是素数
if (n < 2 || !(n & 1)) return false; //如果n是偶数或者是0,1,那它不是素数
while (!(q & 1)) //将n分解成(2^s)*q的样子
{
s++;
q >>= 1;
}
for (i = 0; i < 10 && prime[i] < n; ++i) //随便选一个素数进行测试
{
int a = prime[i];
int b = Quick_Power(a, q, n); //先算出a^q
for (j = 1; j <= s; ++j) //然后进行s次平方
{
k = Quick_Multiply(b, b, n); //求b的平方
if (k == 1 && b != 1 && b != n - 1) //用二次探测判断
return false;
b = k;
}
if (b != 1) return false; //用费马小定律判断
}
return true; //如果进行多次测试都是对的,那么n就很有可能是素数
}
4.测试主函数
int main()
{
long long n = 1;
Euler_prime(1e7);
while (true)
{
cout << "请输入一个数(输入-1退出程序):";
cin >> n;
if (n == -1) exit(0); //退出程序
if (Miller_Rabin(n))
cout << "不确定";
else //合数,素数分解
{
int sign = 0; //做输出标记
cout << "合数\n" << n << "=";
long long remainder = n; //商
for (int i = 0; i < 1e7; i++)
{
long long plus = remainder % prime[i]; //余数
int flag = 0;
while (!plus) //被整除
{
remainder = remainder / prime[i];
plus = remainder % prime[i];
flag++;
}
if (sign && flag != 0)
cout << "*";
if (flag != 0)
{
cout << prime[i] << "^" << flag;
sign++;
}
if (remainder == 1) //分解完毕
break;
}
}
cout << endl;
}
return 0;
}
5.测试实验结果