zoukankan      html  css  js  c++  java
  • 【LOJ#143】质数判定

    题目

    题目链接:https://loj.ac/p/143
    给定一个数 (n),判断是否是质数。
    (nleq 10^{18})

    思路

    Miller–Rabin 素数测试板子题。推荐博客
    质数有两个性质。一是众所周知的费马小定理:若 (p) 是质数,且 (x) 不是 (p) 的倍数,则

    [x^{p-1}equiv 1pmod p ]

    还有一个二次探测定理。如果 (p) 是质数且 (x^2equiv 1pmod p),那么 (xequiv1pmod p)(xequiv p-1pmod p)
    证明直接把 (1) 移项平方差即可。
    所以对于一个要测试的数 (p),我们取一个数 (a),先判断 (a^{p-1}mod p) 是否等于 (1)。如果不是那么显然 (p) 是合数。
    接下来重复此操作:

    1. 如果 (p-1) 是奇数则直接退出循环。
    2. 计算 (a^{frac{p-1}{2}}mod p),根据二次探测定理,如果答案不是 (1)(n)(p) 是合数。
    3. 如果答案是 (1) 则取 (p'=frac{p-1}{2}) 继续探测。

    随机选 (a) 的话,Miller–Rabin 有 (frac{1}{4}) 的概率出错。所以如果测试 (k) 次,测试错误的概率就降至 (frac{1}{4^k})
    在数据范围不同时 (a) 的选取可以参考 wiki

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long double ld;
    typedef long long ll;
    
    const int prm[10]={0,2,3,5,7,11,13,17,19,23};
    ll n;
    
    ll fmul(ll x,ll y,ll MOD)
    {
    	ll z=(ld)x*y/MOD;
    	return ((x*y-z*MOD)%MOD+MOD)%MOD;
    }
    
    ll fpow(ll x,ll k,ll MOD)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=fmul(x,x,MOD))
    		if (k&1) ans=fmul(ans,x,MOD);
    	return ans;
    }
    
    bool MR(ll n)
    {
    	if (n==1) return 0;
    	for (int i=1;i<=9;i++)
    	{
    		if (n==prm[i]) return 1;
    		if (n<prm[i]) return 0;
    		ll m=n-1,power=fpow(prm[i],m,n);
    		while (power==1 && !(m&1))
    			m>>=1,power=fpow(prm[i],m,n);
    		if (power!=1 && power!=n-1) return 0;
    	}
    	return 1;
    }
    
    int main()
    {
    	while (scanf("%lld",&n)!=EOF)
    		if (MR(n)) printf("Y
    ");
    			else printf("N
    ");
    	return 0;
    }
    
  • 相关阅读:
    zz java compare 接口
    moodle 迁移
    Excel 散点图和折线图的区别
    leetcode Two Sum
    jQuery 常用方法大全<2>
    利用JQuery的$.ajax()可以很方便的调用asp.net的后台方法
    回车验证信息
    SQL 创建密码
    高效的分页
    MVC 怎么样设置起始页
  • 原文地址:https://www.cnblogs.com/stoorz/p/14296950.html
Copyright © 2011-2022 走看看