这是一个随机性算法,有可能会被卡!!!
素数是数论中地位突出的一个环节,对于素数的判断同样是研究不断,在我之前的博文中已经简单的说过了欧拉筛,这是一种确定性算法,可以保证得到的结果是准确的,并且在多组数据的判断中很占优势,但其本身的空间复杂度仍是难以处理的一点
而MR素性测试则是很好的处理了这一点,在针对离散型数据的素数判断中在时间与空间上有很大的优势,因为其本身是是从结论的角度去进行的验证性算法。
先说理论,本质是小费马定理的逆运用
/*
* @Author: Gehrychiang
* @LastEditors : Please set LastEditors
* @Website: www.yilantingfeng.site
* @E-mail: gehrychiang@aliyun.com
*/
#include <bits/stdc++.h>
using namespace std;
long long fastMul(long long a, long long b, long long mod) //a*b % mod
{
long long res = 0;
while (b)
{
if (b & 1)
{
res = (res + a) % mod;
}
a = (a + a) % mod;
b >>= 1;
}
return res;
}
long long fastPowMod(long long a, long long n, long long mod) //a^n % mod
{
if (n == 0 && a != 0)
return 1;
if (n != 0 && a == 0)
return 0;
long long base = a;
long long res = 1;
while (n)
{
if (n & 1)
{
res = fastMul(res, base, mod);
}
base = fastMul(base, base, mod);
n >>= 1;
}
return res % mod;
}
bool mr_test(long long n, long long a, long long d)
{
if (n == 2) //n是2
return true;
if (n % 2 == 0) //n为偶数
return false;
if (n == a) //二者相等了,其实这种情况并不会出现,已经在组测试中得到了True的返回值
return false;
// 存在某个i使得a^(d*2^i) mod n=n-1 i>=0
while (!d & 1) //确保d为奇数
{
d >>= 1; // d/=2
}
long long t = fastPowMod(a, d, n);
while (d != n - 1 && t != n - 1 && t != 1)
{
t = fastMul(t, t, n);
d <<= 1; // d*=2 这里用来还原前面的取成奇数的过程也就是把d朝n-1复原的过程
}
return t == n - 1 || t == 1; //如果最后我们的可以等于n-1或是为1那么就是通过了这一组测试
}
bool mr_test_grp(long long n)
{
if (n == 1)
return false;
int a[10] = {2, 3, 5, 7, 11, 13, 17, 19, 47, 61};
for (int i = 0; i < 10; i++)
{
if (n == a[i])
return true;
if (!mr_test(n, a[i], n - 1)) //有一组没通过素性测试
return false;
}
//更多的随机数样本测试,一般来说,工业级代码需要要求通过1k组以上的测试才能保证判断的准确性
// srand(5201314);
// for (int i = 0; i < 33; i++)
// {
// long long r=rand()%(n-1)+1;
// if(n==r)
// return true;
// if(!mr_test(n,r,n-1))
// return false;
// }
return true; //全部通过 此时大概率是素数
}
int main()
{
long long n;
cin >> n;
if (mr_test_grp(n))
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
return 0;
}
- /*
- * @Author: Gehrychiang
- * @LastEditors : Please set LastEditors
- * @Website: www.yilantingfeng.site
- * @E-mail: gehrychiang@aliyun.com
- */
- #include <bits/stdc++.h>
- using namespace std;
- long long fastMul(long long a, long long b, long long mod) //a*b % mod
- {
- long long res = 0;
- while (b)
- {
- if (b & 1)
- {
- res = (res + a) % mod;
- }
- a = (a + a) % mod;
- b >>= 1;
- }
- return res;
- }
- long long fastPowMod(long long a, long long n, long long mod) //a^n % mod
- {
- if (n == 0 && a != 0)
- return 1;
- if (n != 0 && a == 0)
- return 0;
- long long base = a;
- long long res = 1;
- while (n)
- {
- if (n & 1)
- {
- res = fastMul(res, base, mod);
- }
- base = fastMul(base, base, mod);
- n >>= 1;
- }
- return res % mod;
- }
- bool mr_test(long long n, long long a, long long d)
- {
- if (n == 2) //n是2
- return true;
- if (n % 2 == 0) //n为偶数
- return false;
- if (n == a) //二者相等了,其实这种情况并不会出现,已经在组测试中得到了True的返回值
- return false;
- // 存在某个i使得a^(d*2^i) mod n=n-1 i>=0
- while (!d & 1) //确保d为奇数
- {
- d >>= 1; // d/=2
- }
- long long t = fastPowMod(a, d, n);
- while (d != n - 1 && t != n - 1 && t != 1)
- {
- t = fastMul(t, t, n);
- d <<= 1; // d*=2 这里用来还原前面的取成奇数的过程也就是把d朝n-1复原的过程
- }
- return t == n - 1 || t == 1; //如果最后我们的可以等于n-1或是为1那么就是通过了这一组测试
- }
- bool mr_test_grp(long long n)
- {
- if (n == 1)
- return false;
- int a[10] = {2, 3, 5, 7, 11, 13, 17, 19, 47, 61};
- for (int i = 0; i < 10; i++)
- {
- if (n == a[i])
- return true;
- if (!mr_test(n, a[i], n - 1)) //有一组没通过素性测试
- return false;
- }
- //更多的随机数样本测试,一般来说,工业级代码需要要求通过1k组以上的测试才能保证判断的准确性
- // srand(5201314);
- // for (int i = 0; i < 33; i++)
- // {
- // long long r=rand()%(n-1)+1;
- // if(n==r)
- // return true;
- // if(!mr_test(n,r,n-1))
- // return false;
- // }
- return true; //全部通过 此时大概率是素数
- }
- int main()
- {
- long long n;
- cin >> n;
- if (mr_test_grp(n))
- {
- cout << "yes" << endl;
- }
- else
- {
- cout << "no" << endl;
- }
- return 0;
- }
/*
* @Author: Gehrychiang
* @LastEditors : Please set LastEditors
* @Website: www.yilantingfeng.site
* @E-mail: gehrychiang@aliyun.com
*/
#include <bits/stdc++.h>
using namespace std;
long long fastMul(long long a, long long b, long long mod) //a*b % mod
{
long long res = 0;
while (b)
{
if (b & 1)
{
res = (res + a) % mod;
}
a = (a + a) % mod;
b >>= 1;
}
return res;
}
long long fastPowMod(long long a, long long n, long long mod) //a^n % mod
{
if (n == 0 && a != 0)
return 1;
if (n != 0 && a == 0)
return 0;
long long base = a;
long long res = 1;
while (n)
{
if (n & 1)
{
res = fastMul(res, base, mod);
}
base = fastMul(base, base, mod);
n >>= 1;
}
return res % mod;
}
bool mr_test(long long n, long long a, long long d)
{
if (n == 2) //n是2
return true;
if (n % 2 == 0) //n为偶数
return false;
if (n == a) //二者相等了,其实这种情况并不会出现,已经在组测试中得到了True的返回值
return false;
// 存在某个i使得a^(d*2^i) mod n=n-1 i>=0
while (!d & 1) //确保d为奇数
{
d >>= 1; // d/=2
}
long long t = fastPowMod(a, d, n);
while (d != n - 1 && t != n - 1 && t != 1)
{
t = fastMul(t, t, n);
d <<= 1; // d*=2 这里用来还原前面的取成奇数的过程也就是把d朝n-1复原的过程
}
return t == n - 1 || t == 1; //如果最后我们的可以等于n-1或是为1那么就是通过了这一组测试
}
bool mr_test_grp(long long n)
{
if (n == 1)
return false;
int a[10] = {2, 3, 5, 7, 11, 13, 17, 19, 47, 61};
for (int i = 0; i < 10; i++)
{
if (n == a[i])
return true;
if (!mr_test(n, a[i], n - 1)) //有一组没通过素性测试
return false;
}
//更多的随机数样本测试,一般来说,工业级代码需要要求通过1k组以上的测试才能保证判断的准确性
// srand(5201314);
// for (int i = 0; i < 33; i++)
// {
// long long r=rand()%(n-1)+1;
// if(n==r)
// return true;
// if(!mr_test(n,r,n-1))
// return false;
// }
return true; //全部通过 此时大概率是素数
}
int main()
{
long long n;
cin >> n;
if (mr_test_grp(n))
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
return 0;
}