BZOJ 3667 Rabin-Miller算法 Pollard-Rho算法 数论专题第八题

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/86495669

题目p2107

LUOGU 4718

From Tyvj Guest☆bzoj3667 Rabin-Miller算法
背景 Background
此系列问题为数论专题
具体参考博文
http://blog.csdn.net/chty2018/article/details/53432272
描述 Description
给定一个CAS,以下CAS行,每行一个数字,保证在64位长整形范围内,并且没有负数。
你需要对于每个数字:
第一,检验是否是质数,是质数就输出Prime
第二,如果不是质数,输出它最大的质因子是哪个。
输入格式 Input Format
第一行CAS(CAS<=350,代表测试数据的组数)
以下CAS行:每行一个数字,保证是在64位长整形范围内的正数。
输出格式 Output Format
对于每组测试数据:输出Prime,代表它是质数,或者输出它最大的质因子,代表它是和数
样例输入 Sample Input
6
2
13
134
8897
1234567654321
1000000000000
样例输出 Sample Output
6
2
13
134
8897
1234567654321
1000000000000
时间限制 Time Limitation
1s
注释 Hint
1s
来源 Source
题面,数据来自宋逸群

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll a[]={2,3,5,7,11,13,17,19,23,29};
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    static ll f=1;
    static char ch=getc();
    while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getc(); }
    while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48), ch=getc();
    x*=f;
}
template<typename T>inline void write(T x)
{
  if (x<0) x=-x,putchar('-');
  if (x>9) write(x/10);
  putchar(x%10+'0');
}
inline ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
inline ll mul(ll a,ll b,ll p)
{
    ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
    return tmp<0?tmp+p:tmp;
}
inline ll power(ll a,ll b,ll p)
{
    ll ans=1;
    a%=p;
    while (b)
    {
        if (b&1)
            ans=mul(ans,a,p);
        a=mul(a,a,p);
        b>>=1;
    }
    return ans;
}
inline bool check(ll a,ll n,ll r,ll s)
{
    ll ans=power(a,r,n),p=ans;
    for (register int i=1;i<=s;++i)
    {
        ans=mul(ans,ans,n);
        if (ans==1 && p!=1 && p!=n-1) return 1;
        p=ans;
    }
    if (ans!=1) return 1;
    return 0;
}
inline bool RabinMiller(ll n)
{
    if (n<=1)	return 0;
    if (n==2)	return 1;
    if (n%2==0)	return 0;
    ll r=n-1,s=0;
    while (r%2==0)
        r>>=1,++s;
    for (register int i=0;i<10;++i) 
        if (check(rand()%(n-1)+1,n,r,s))
			return 0;
    return 1;
}
inline ll PollardRho(ll n,ll c)
{
    ll k=2,x=rand()%n,y=x,p=1;
    for (register ll i=1;p==1;++i)
    {
        x=(mul(x,x,n)+c)%n;
        p=gcd(n,abs(x-y));
        if (i==k) y=x,k<<=1;
    }
    return p;
}
ll mx;
inline void find(ll n)
{
    if (n==1) return ;
    if (RabinMiller(n))
    {
        mx=max(mx,n);
        return ;
    }
    ll t=n;
    while (t==n)
        t=PollardRho(n,rand()%(n-1)+1);
    find(t),find(n/t);
}
int main()
{
    ll t;read(t);
    while (t--)
    {
        ll x;read(x);
        mx=0;
        find(x);
        if (mx==x)
            puts("Prime");
        else
            write(mx),putchar('\n');
    }
    return 0;
}

这是个很正经的代码。。。。。。。然而最后一个点T。。。。。。。。。。。
然后发现评论区出现了位大佬,他的代码。。。。。。。。。。。。。。。反正A了。。。。而且跑的飞快。。。。。。。。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (1 << 7) - 1;
const int pr[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
//平台无关式longlong乘法取模
ll mmul(ll a, ll b, ll m)
{
    ll d = ((long double)a / m * b + 1e-8);
    ll r = a * b - d * m;
    return r < 0 ? r + m : r;
}

ll mpow(ll a, ll b, ll m)
{
    ll r = 1;
    for (; b; b >>= 1, a = mmul(a, a, m))
        if (b & 1) r = mmul(r, a, m);
    return r;
}
//玄学位运算版gcd
ll gcd(ll a, ll b)
{
    if (!a) return b;
    if (!b) return a;
	#define ctz __builtin_ctzll
    int t = ctz(a | b);
    a >>= ctz(a);
    do
	{
        b >>= ctz(b);
        if (a > b)
		{
            ll t = b;
            b = a;
            a = t;
        }
        b -= a;
    } while (b != 0);
    return a << t;
}

int prime(ll n)
{
    if (n == 1) return 0;
    if (n == 2 || n == 3 || n == 5) return 1;
    //瞬间排除掉73.33%的数 O_O
    if (!(n & 1) || (n % 3 == 0) || (n % 5 == 0)) return 0;
    ll m = n - 1;
    int k = 0;
    while (!(m & 1)) m >>= 1, k++;
    for (int ip = 0; ip < 12 && pr[ip] < n; ++ip)
	{
        ll x = mpow(pr[ip], m, n), y = x;
        for (int i = 0; i < k; ++i)
		{
            x = mmul(x, x, n);
            if (x == 1 && y != 1 && y != n - 1) return 0;
            y = x;
        }
        if (x != 1) return 0;
    }
    return 1;
}
inline ll g(ll x, ll n, ll a)
{
    ll t = mmul(x, x, n) + a;
    return t < n ? t : t - n;
}
ll rho(ll n)
{
    //又来特判了。。。
    if (n % 2 == 0) return 2;
    if (n % 3 == 0) return 3;
    ll x = 0, y = x, t = 1, q = 1, a = (rand() % (n - 1)) + 1;
    for (int k = 2;; k <<= 1, y = x, q = 1)
	{
        for (int i = 1; i <= k; ++i)
		{
            x = g(x, n, a);
            q = mmul(q, abs(x - y), n);
            if (!(i & M))
			{
                t = gcd(q, n);
                if (t > 1) break;
            }
        }
        if (t > 1 || (t = gcd(q, n)) > 1) break;
    }
    if (t == n)
	{
        t = 1;
        while (t == 1)
			t = gcd(abs((x = g(x, n, a)) - y), n);
    }
    return t;
}
ll f[105];
int tot;
void work(ll n)
{
    if (n == 1) return;
    if (prime(n))
	{
        f[tot++] = n;
        return;
    }
    ll t = n;
    while (t == n) t = rho(n);
    work(t);
    work(n / t);
}

int main()
{
    srand(19260817);
    int t;ll n;
    cin >> t;
    while (t--)
	{
        cin >> n;
        tot = 0;
        work(n);
        sort(f, f + tot);
        if (tot == 1)
            cout << "Prime" << endl;
        else
            cout << f[tot - 1] << endl;
    }
    return 0;
}

对此,我。。。。。。只能无语。

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/86495669
今日推荐