poj 1811 随机素数和大数分解(模板)

 

Sample Input

2
5
10

Sample Output

Prime
2

 

模板学习:

判断是否是素数,数据很大,所以用miller,不是的话再用pollard rho分解

miller : 通过费马小定理,若N为素数,a^(N-1) = 1 (mod N),

再利用二次判定:

若x为素数,0<x<p, x*x = 1(mod q)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <time.h>
#define N 10100
typedef long long ll;
using namespace std;
 
const int S = 8;       //随机判定次数  一般8 - 10
 
// a*b%c
ll mult_mod(ll a,ll b,ll c)
{
    a %= c;
    b %= c;
    ll ret = 0;
    ll temp = a;
    while(b)
    {
        if(b&1)
        {
            ret += temp;
            if(ret > c) ret -= c;
        }
        temp <<= 1;
        if(temp > c) temp -= c;
        b >>= 1;
    }
    return ret;
 
}
 
// (a^n)%mod
ll pow_mod(ll a,ll n,ll mod)             
{
    ll ret = 1;
    ll temp = a%mod;
    while(n)
    {
        if(n & 1)
            ret = mult_mod(ret,temp ,mod);
        temp = mult_mod(temp,temp,mod);
        n>>= 1;
    }
    return ret;
}
//通过费马小定理,a^(n-1)=1(mod n) ;来判断n是否是素数
bool check(ll a,ll n,ll x,ll t)
{
    ll ret = pow_mod(a,x,n);
    ll last = ret;
    for(int i = 1; i <= t; i++)
    {
        ret = mult_mod(ret,ret,n);      //二次探测
        if(ret == 1 && last != 1 && last != n-1) return true;
        last = ret;
    }
    if(ret != 1)  return true;
    else  return false;
}
 
bool miller_rabin(ll n)            //随机素数
{
    if(n < 2) return false;
    if(n == 2) return true;
    if((n&1) == 0)  return false;   //偶数
    ll x = n - 1;
    ll t = 0;
    while((x&1) == 0)
    {
        x>>= 1;
        t++;
    };
    srand(time(NULL));       //G++时不要
 
    for(int i = 0; i < S; i++)
    {
        ll a = rand()%(n - 1) + 1;
        if(check(a,n,x,t))
            return false;
    }
    return true;
}
 
ll factor[100];
int tol;
 
ll gcd(ll a,ll b)
{
    ll t;
    while(b)
    {
        t = a;
        a = b;
        b = t % b;
    }
    if(a >= 0) return a;
    else
        return -a;
}
//找因子
ll pollard_rho(ll x,ll c)
{
    ll i = 1,k = 2;
    srand(time(NULL));
    ll x1 = rand()%(x-1)+1;
    ll y = x1;
    while(1)
    {
        i++;
        x1 = (mult_mod(x1,x1,x)+c)%x;
        ll d = gcd(y-x1,x);
        if(d!=1 && d!=x) return d;
        if(y == x1) return x;
        if(i == k)
        {
            y = x1;
            k += k;
        }
    }
}
//对n进行分解,存入数组,
void findfac(ll n,int k)           //大数分解
{
    if(n == 1)
        return ;
    if(miller_rabin(n))       //判素
    {
        factor[tol++] = n;
        return ;
    }
    ll p = n;
    int c = k;
    while( p>= n)
        p = pollard_rho(p,c--);     //防止死循环k,值变换
    findfac(p,k);
    findfac(n/p,k);
 
}
 
int main()
{
    int t;
    ll n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d",&n);
        if(miller_rabin(n))  printf("Prime\n");
        else
        {
            tol = 0;
            findfac(n,107);
            ll ans = factor[0];
            for(int i = 1; i < tol; i++)
                ans = min(ans,factor[i]);
            printf("%I64d\n",ans);
        }
    }
    return 0;
}

  

posted @   Przz  阅读(166)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· SQL Server统计信息更新会被阻塞或引起会话阻塞吗?
阅读排行:
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 本地部署 DeepSeek:小白也能轻松搞定!
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 普通人也能轻松掌握的20个DeepSeek高频提示词(2025版)
点击右上角即可分享
微信分享提示