• [luogu4718]Pollard-Rho算法


    模板题

    题解主要分为两部分,即Miller-Robin判素数以及关于Pollard-Rho算法

    1.Miller-Robin判素数

    对于一个数$n$,判定其是否为素数,依次执行以下几步——

    (1)若$n=2$在$n$为素数,否则若$n=1$或$nequiv 0(mod 2)$则$n$非素数

    (2)对于一个素数$p$,分类讨论

    若$(p,n) e 1$($=p$),显然根据$p$是否等于$n$可以直接确定$n$是否为素数

    若$(p,n)=1$,根据费马小定理要求$p^{n-1}equiv 1(mod n)$

    同时若$n$为素数,$x^{2}equiv 1(mod n)$的解仅有$xequiv 1或n-1(mod n)$(将其分解即可)

    假设$n-1=2^{k}m$,则$forall 1le ile k$且$p^{2^{i}m}equiv 1(mod n)$,满足$p^{2^{i-1}m}equiv 1或n-1(mod n)$

    (3)重复第2个步骤若干次(当然可以预先选好素数)

    2.Pollard-Rho算法

    基本思路

    考虑对$n$进行质因数分解,先使用Miller-Robin在$o(log n)$的时间内判定$n$是否是素数,若$n$为素数即结束,否则需要快速找到一个$1le x<n$且$gcd(n,x)>1$,之后递归分解$gcd(x,n)$和$frac{n}{gcd(n,x)}$即可

    构造方式

    关于如何找到$x$,我们考虑如下的方式:

    构造一个序列$a_{i}$,其中$a_{i}=a_{i-1}^{2}+c(ige 2)$,$a_{1}$和$c$均为随机

    (关于这个递推式并没有太大的实际意义,只是$a_{i}$由$a_{i-1}$唯一确定且分布较为随机)

    从小到大枚举$ige 1$,并令$xequiv a_{i}-a_{2i}(mod n)$(要求$0le x<n$),若$x=0$则重新随机$a_{1}$和$c$并再次执行,否则判定$x$是否满足条件($gcd(n,x)>1$),若满足条件即可递归

    复杂度分析

    下面,我们来考虑找到$x$的期望$i$大小或无法找到的概率——

    先考虑另外一个问题,对于一个$n$,第一次出现$a_{i}equiv a_{2i}(mod n)$的位置

    令$x$为最小的整数,满足$exists 1le y<x$且$a_{x}equiv a_{y}(mod n)$,显然$y$是唯一的,再取这个唯一的$y$

    考虑序列${a_{i} mod n}$,根据$a_{i}$由$a_{i-1}$唯一确定(在模意义下显然也满足),$x$和$y$实际上分别是第2次和第1次进入循环的位置,更具体的有$forall ige y,a_{i}equiv a_{i+(x-y)}(mod n)$

    在$[y,x)$中取$kequiv 0(mod x-y)$(显然唯一),根据循环的性质不难得到$a_{k}equiv a_{2k}(mod n)$,且由于$x$和$y$最小的性质,还可以证明$k$也是最小的,即$k$就是这个位置

    再考虑$k$的期望,由于$k<x$也可以看作$x$的期望,由于序列$a_{i}$分布可以认为是随机的,根据$x$的定义可以发现$x$的期望即在$[0,n)$范围内随机若干次出现重复数字的期望次数

    根据生日悖论,其期望是$o(sqrt{n})$的,具体推导如下——

    考虑$P(xle X)$(即$xle X$的概率),等价于$X$个数中存在相同,不难得到$P(X)=1-prod_{i=0}^{X-1}(1-frac{i}{n})$

    根据均值不等式,有$sqrt[X]{prod_{i=0}^{X-1}(1-frac{i}{n})}le {frac{1}{X}sum_{i=0}^{X-1}(1-frac{i}{n})}=frac{2n-X+1}{n}$

    代入后,即$P(X)ge 1-(frac{2n-X+1}{2n})^{X}=1-(1-frac{X}{2n})^{X}$

    由于$frac{1}{1-x}=sum_{i=0}^{infty}x^{i}$,而根据泰勒展开有$e^{x}=sum_{i=0}^{infty}frac{1}{i!}x^{i}<frac{1}{1-x}$,即$1-x<e^{-x}$

    将之代入,即$P(X)ge 1-e^{-frac{X^{2}}{2n}}ge frac{1}{2}$,即$e^{-frac{X^{2}}{2n}}le frac{1}{2}$,$Xge sqrt{-2nlnfrac{1}{2}}sim o(sqrt{n})$

    (真的求期望$E(x)$也就要对$sum_{i=0}^{n-1}(e^{-frac{1}{2n}})^{i^{2}}$求值,可能比较困难)

    考虑完这个问题后,回归原问题,令$p$为$n$的最小素因子(显然$ple sqrt{n}$),那么$gcd(n,x)>1$的充分条件是$p|x$,而$p|x$(且$x e 0$)这个条件还可以被表述为:$a_{i} otequiv a_{2i}(mod n)$且$a_{i}equiv a_{2i}(mod p)$

    根据前面的结论,$a_{i}equiv a_{2i}(mod p)$的期望位置是$o(sqrt{p})$的

    但还有一个问题,即有可能同时还满足$a_{i}equiv a_{2i}(mod n)$,此时$x=0$,即无法找到

    但由于前者期望位置是$o(sqrt{n})$的,后者是$o(sqrt{p})$的,两者并不同阶,因此这个概率并不大,可以认为在$o(1)$次内一定可以找到(这里应该是极其口胡的,但并不知道如何更严谨的说明QAQ)

    每一次查找(包括失败)复杂度都是期望$o(sqrt{p})$,查找次数又是$o(1)$,再算上$gcd$的复杂度,因此单次分解复杂度即为$o(sqrt{p}log n)$

    虽然至多有$o(log n)$次递归,而$p$又是$o(sqrt{n})$的,总复杂度即$o(n^{frac{1}{4}}log^{2}n)$,但事实上这个复杂度还可以进一步的精确——

    (以下过程通俗的来说,即若递归次数过多则$p$一定很小,当$p$是$o(sqrt{n})$这个级别时递归次数是$o(1)$的,因此复杂度是$o(n^{frac{1}{4}}log n)$的)

    考虑递归后分别是$d$和$frac{n}{d}$,其中较小的不超过$sqrt{n}$,其复杂度根据前面是$o(n^{frac{1}{8}}log^{2}n)$,可以忽略,换言之递归时我们仅关心于大于$sqrt{n}$的部分的复杂度

    不妨假设$d>sqrt{n}$,那么$n$的最小素因子不超过$frac{n}{d}$,即$T(n)=max_{d|n}T(d)+sqrt{frac{n}{d}}log n$

    对于其中$frac{n}{d}le n^{frac{1}{4}}$(前面的$n$指该次递归,后者的$n$指全局),即使有$log$次复杂度也仅为$o(n^{frac{1}{8}}log^{2}n)$,同样可以忽略,而若$frac{n}{d}>n^{frac{1}{4}}$,那么即至多4次,总复杂度为$o(n^{frac{1}{4}}log n)$

    综上,即说明了复杂度为$o(n^{frac{1}{4}}log n)$

    关于gcd的优化

    可以将若干次gcd组合在一起计算,即若求$gcd(x,n)$和$gcd(y,n)$,不妨直接求$gcd(xy mod n,n)$

    但这样就不能每一次都判定,可以考虑隔一段时间判定一次,关于这个间隔比较随意,只需在$[log n,n^{frac{1}{4}}]$中,即可令复杂度降为$o(n^{frac{1}{4}})$,另外在$x=0$时还需要将之前的再求一次

    (另外可能会涉及模$n$意义下两数乘法,需要使用int128或其他技巧)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 int t,p[5]={3,5,7,11,13};
     5 ll n;
     6 ll mul(ll x,ll y,ll n){
     7     return (__int128)x*y%n;
     8 }
     9 ll gcd(ll x,ll y){
    10     if (!y)return x;
    11     return gcd(y,x%y);
    12 }
    13 ll pow(ll n,ll m,ll mod){
    14     ll s=n,ans=1;
    15     while (m){
    16         if (m&1)ans=mul(ans,s,mod);
    17         s=mul(s,s,mod);
    18         m>>=1;
    19     }
    20     return ans;
    21 }
    22 bool check(ll n){
    23     if (n==2)return 1;
    24     if (n%2==0)return 0;
    25     ll m=n-1,k=0;
    26     while (m%2==0){
    27         k++;
    28         m/=2;
    29     }
    30     for(int i=0;i<5;i++){
    31         if (n%p[i]==0)return n==p[i];
    32         ll s=pow(p[i],m,n);
    33         for(int j=0;j<k;j++){
    34             if ((mul(s,s,n)==1)&&(s!=1)&&(s!=n-1))return 0;
    35             s=mul(s,s,n);
    36         }
    37         if (s>1)return 0;
    38     }
    39     return 1;
    40 }
    41 ll get_fac(ll n){
    42     ll x=rand()%n,c=rand()%n,y=(mul(x,x,n)+c)%n,z=1,tot=0;
    43     while (1){
    44         if ((x==y)||(tot%100==0)){
    45             if (gcd(z,n)>1)return gcd(z,n);
    46             if (x==y)return 1;
    47             z=1;
    48         }
    49         tot++;
    50         z=mul(z,(x+n-y)%n,n);
    51         if (!z)return gcd((x+n-y)%n,n);
    52         x=(mul(x,x,n)+c)%n;
    53         y=(mul(y,y,n)+c)%n;
    54         y=(mul(y,y,n)+c)%n;
    55     }
    56 }
    57 ll calc(ll n){
    58     if (check(n))return n;
    59     while (1){
    60         ll p=get_fac(n);
    61         if (p>1)return max(calc(p),calc(n/p));
    62     }
    63 }
    64 int main(){
    65     srand(time(0));
    66     scanf("%d",&t);
    67     while (t--){
    68         scanf("%lld",&n);
    69         ll ans=calc(n);
    70         if (ans==n)printf("Prime
    ");
    71         else printf("%lld
    ",ans);
    72     }
    73 }
    View Code
  • 相关阅读:
    元素的高度自适应
    关于IE6的一些常见的CSS BUG处理
    Vue项目在IE浏览器报错polyfilleventsource added missing EventSource to window
    Springboot使用JdbcTemplate RowMapper查询,直接返回实体列表
    Springboot启动工程后,浏览器出现输入用户名和密码
    mysql5.6 zip版本如何安装
    python基础基础知识介绍
    python基础数据类型,集合及深浅copy
    格式化输出
    python基础windows环境下 安装python2和python3
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14602264.html
Copyright © 2020-2023  润新知