• 【洛谷P4718】【模板】Pollard-Rho算法


    题目

    题目链接:https://www.luogu.com.cn/problem/P4718
    Miller Rabin 算法是一种高效的质数判断方法。虽然是一种不确定的质数判断法,但是在选择多种底数的情况下,正确率是可以接受的。
    Pollard Rho是一个非常玄学的方式,用于在(O(n^{1/4}))的期望时间复杂度内计算合数n的某个非平凡因子。事实上算法导论给出的是(O(sqrt p))(p)(n)的某个最小因子,满足(p)(n/p)互质。但是这些都是期望,未必符合实际。但事实上Pollard Rho算法在实际环境中运行的相当不错。
    这里我们要写一个程序,对于每个数字检验是否是质数,是质数就输出Prime;如果不是质数,输出它最大的质因子是哪个。
    (Tleq 350,nleq 10^{18})

    思路

    嗯好
    反正玄学就完事了。
    注意光速乘的时候不要 (res%MOD+MOD)%MOD,常数巨大。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    
    const int prm[10]={0,2,3,5,7,11,13,17,19,23};
    int Q;
    ll n,maxd;
    
    ll fmul(ll x,ll y,ll MOD)
    {
    	ll z=(ld)x*y/MOD,res=x*y-z*MOD;
    	if (res<0) return res+MOD;
    	if (res>=MOD) return res-MOD;
    	return res;
    }
    
    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;
    }
    
    ll gcd(ll x,ll y)
    {
    	return y?gcd(y,x%y):x;
    }
    
    bool MR(ll n)
    {
    	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;
    }
    
    ll work(ll n)
    {
    	ll val=1,s=0,t=0,c=rand()%(n-1);
    	for (int lim=1,i=1;;i++)
    	{
    		t=(fmul(t,t,n)+c)%n;
    		val=fmul(val,abs(t-s),n);
    		if (i==lim || i%127==0)
    		{
    			ll d=gcd(val,n);
    			if (d>1) return d;
    			if (i==lim) s=t,val=1,lim<<=1;
    		}
    	}
    }
    
    void PR(ll n)
    {
    	if (n<=maxd || n<2) return;
    	if (MR(n)) { maxd=n; return; }
    	ll d=work(n);
    	while (d>=n) d=work(n);
    	while (n%d==0) n/=d;
    	PR(n); PR(d);
    }
    
    int main()
    {
    	scanf("%d",&Q);
    	while (Q--)
    	{
    		scanf("%lld",&n);
    		srand(13331U*(Q+2333)*n);
    		maxd=0; PR(n);
    		if (maxd==n) printf("Prime
    ");
    			else printf("%lld
    ",maxd);
    	}
    	return 0;
    }
    
  • 相关阅读:
    344. 反转字符串
    942. 增减字符串匹配
    CGO内部机制
    CGO函数调用
    CGO类型转换
    CGO基础
    Go net/http代理
    GO-中间件(Middleware )
    Go如何巧妙使用runtime.SetFinalizer
    ARM基础
  • 原文地址:https://www.cnblogs.com/stoorz/p/14298366.html
Copyright © 2020-2023  润新知