素数的判定

米勒罗宾算法
bool test (LL n,LL a,LL d)
{
  if(n==2)
    return true;
  if(n==a)
    return true;
  if((n&1)==0)
    return false;
  while(!(d&1))
    d=d>>1;
  LL t=pow_mod(a,d,n);
  while((d!=n-1)&&(t!=1)&&(t!=n-1))
  {
    t=(LL)t*t%n;
    d=d<<1;
  }
  return (t==n-1||(d&1)==1);
}
bool isPrime(LL n)
{
  if(n<2)
    return false;
  LL a[]= {2,3,5,7,61};
  for(int i=0; i<=4; i++)
    if(!test(n,a[i],n-1))
      return false;
  return true;
}
 
int p[10005],a[10005];
void prime()  
{  
    int i,n=10005,t=1,j;  
    a[1]=0;  
    for(i=2;i<=n;i++)
		a[i]=1;  
    for(i=2;i<=n;i++)  
        if(a[i])
		{  
            p[t++]=i; 
            for(j=i;j<=n;j+=i)
				a[j]=0;  
        }  
}  
//t要从1开始 从0开始第一个2会变成0 好奇怪。。。
int prime(int n)
{
    int i,q;
    q=(int)sqrt(n);
    for(i=0;p[i]<=q;i++)
        if(n%p[i]==0)return 0;
    return 1;
}
int p[8]={4,2,4,2,4,6,2,6};
int prime(int n)
{
    int i=7,j,q;
    if(n==1)return 0;
    if(n==2||n==5||n==3)return 1;
    if(n%2==0||n%3==0||n%5==0)return 0;
    q=(int)sqrt(n);
    for(;i<=q;){
        for(j=0;j<8;j++){
            if(n%i==0)return 0;
            i+=p[j];
        }
        if(n%i==0)return 0;
    }
    return 1;
}
米勒罗宾算法的核心是课上提到的费马小定理:
   即如果一个数n 它的 a^(n-1)%n !=1 (0
   如果 a^(n-1)%n ==1 (0)
   1 随机取一个 a
   2 如果 它不满足 a^(n-1)%n ==1
   3 则它一定是 合数
   4 退出
   5 如果它满足 a^(n-1)%n ==1
   6  则它是一个素数的概率是1/2
   7 回到 1
    如果对这个过程重复50次,每次都没说它是合数,那这个数是素数的概率是多少那?
    它只有(1/2)^50可能不是素数!
    很显然就像是投硬币那样如果你投了1000次,每次都投到正面 ,那你就会怀疑这个硬币2面都是正面!
    米勒罗宾算法的算法很简单,但是由于需要计算a^(n-1)%n这类的问题,如果不经行优化,对于大数计算时间复杂度仍旧很高。
     下面Witness(long a,long n)这个函数就是用java实现的a^(n-1)%n的比较快速的大数计算。
     Witness计算的核心是"模运算"
 把a 分解成 t个2 和 奇数u的乘积 ,比如 144 可以分解成4个2 和一个9的乘积
 于是根据"模运算",我们可以把计算a^(n-1)%n,分解成计算 4次(a^2)迭代计算和a^9%n的计算
 对于4次(a^2)迭代计算,只需一个for,执行 t次
 对于a^9%n的计算可参考Modular_Exponentiation(long a, long b,long n)实现
 具体方法为
  定义一个数d为结果,初始值为1
  将9化为2进制1001(2^0方位是第一位)共四位
  则做四次操作
   d=d*d%n
   如果当前位为1则再做
   d=d*a%n


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值