1186 质数检测 V2
这题第一眼看见就想到了以前见过的概率测素数Miller-Robin 素数测试法,但是一看数据是1e30,所以感觉得写大数,但是想了一下__int128能过,就直接用了。
C++的正解是大数 + Miller-Robin 素数测试。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 100;
int S = 50;
__int128 read(){
__int128 x=0,f=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1;
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
void print(__int128 x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10+'0');
}
__int128 mul(__int128 a, __int128 b, __int128 p)
{
__int128 rn=0, i;
for(i=1; i<=b; i<<=1,a=(a+a)%p)
if(b&i) rn=(rn+a)%p;
return rn;
} // 计算模意义下两大数乘积
__int128 ksm(__int128 a, __int128 b, __int128 p)
{
__int128 rn=1;
for(; b; a=mul(a,a,p),b>>=1)
if(b&1) rn=mul(rn,a,p);
return rn;
} // 计算模意义下两大数乘方
LL gcd(LL a, LL b)
{
LL tmp; if(a<b) tmp=a,a=b,b=tmp;
while(b) tmp=a%b, a=b, b=tmp;
return a;
} // 求最大公约数
bool isprime(__int128 n)
{
if(n==2) return true;
if(n<2 || !(n&1)) return false;
__int128 a,x,y, u=n-1; int t=0;
while((u&1)==0) t++, u>>=1;
for(int i=0; i<S; i++)
{
a=rand()%(n-1)+1;
x=ksm(a,u,n);
for(int j=1; j<=t; j++)
{
y=mul(x,x,n);
if(y==1 && x!=1 && x!=n-1) return false;
x=y;
}
if(x!=1) return false;
}
return true;
}
int main()
{
__int128 n;
n = read();
if (isprime(n))
cout << "Yes" << endl;
else
cout << "No" << endl;
return 0;
}
下面是好用的 java。
import java.util.*;
import java.math.*;
public class zhishujiance {
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
BigInteger x;
x=cin.nextBigInteger();
if(x.isProbablePrime(1))
System.out.println("Yes");
else
System.out.println("No");
}
}
没错,就这么几行代码,所以以后遇到大数素数判定还是用java写吧QWQ。