ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

 

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1162

数据范围大约是2^97,需要高精度计算

可以使用pollard-rho算法,期望需要$O((logn)^{1/4})$次整数操作

需要采用 蒙哥马利约化(Montgomery reduction)避免大量取模,并每隔一段时间检查一次gcd。

#include<bits/stdc++.h>
typedef __int128 num;
typedef long long i64;
const int B=50000,K=20;
bool np[B+7];
int ps[B],pp=0,pps[B],fp=0,qp=0;
num fs[111],P,qs[111];
num read(){
    num x=0;
    int c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();
    return x;
}
void pr(num x){
    if(x<0)putchar('-'),x=-x;
    int ss[55],sp=0;
    do ss[++sp]=x%10;while(x/=10);
    while(sp)putchar(48+ss[sp--]);
    putchar(32);
}
num rnd(){
    static std::mt19937 mt(time(0));
    num z=mt();
    z=z<<32^mt();
    z=z<<32^mt();
    return z%(P-1)+1;
}
const unsigned X=(1<<27)-1;
inline num fix1(num a){return a>=P?a-P:a;}
inline num fix2(num a){return a<0?a+P:a;}
inline num mm(num a,num b,num C=0){
    unsigned b0=b&X;b>>=27;
    unsigned b1=b&X;b>>=27;
    unsigned b2=b&X;b>>=27;
    unsigned b3=b&X;
    num c=a*b3%P;
    c=((c<<27)+a*b2)%P;
    c=((c<<27)+a*b1)%P;
    c=((c<<27)+a*b0+C)%P;
    return c;
}
num iP,RR,iR;
#define HI(x) u64((x)>>52)
#define LO(x) u64(x&((1ll<<52)-1))
typedef unsigned __int128 u128;
typedef unsigned long long u64;
const num R=num(1)<<104,R1=R-1;
__attribute__((optimize("Ofast")))
inline u128 mul(u128 a,u128 b){
    u128 m=a*b*iP&R1;
    u128 t=(
        (u128)HI(a)*HI(b)+
        (u128)HI(m)*HI(P)
    );
    u128 t1=(
        (u128)HI(a)*LO(b)+
        (u128)LO(a)*HI(b)+
        (u128)HI(m)*LO(P)+
        (u128)LO(m)*HI(P)
    );
    u128 t0=(
        (u128)LO(a)*LO(b)+
        (u128)LO(m)*LO(P)
    );
    t+=HI(HI(t0)+LO(t1))+HI(t1);
    return fix1(t);
}
inline u128 mulRR(u128 a){return mul(a,RR);}
num exgcd(num a,num b,num&x,num&y){
    if(!b){x=1,y=0;return a;}
    num g=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return g;
}
void setP(num x){
    P=x;
    exgcd(P,R,iP,iR);
    iP=R1&-iP;
    iR=fix2(iR);
    RR=mm(R%P,R%P);
}
num pw(num a,num n){
    num v=1;
    for(;n;n>>=1,a=mm(a,a))if(n&1)v=mm(v,a);
    return v;
}
bool mr(){
    num s=P-1;
    int r=0;
    for(;~s&1;s>>=1,++r);
    num a=pw(rnd(),s);
    for(;;){
        if(a==1||a==P-1)return 1;
        if(!--r)return 0;
        a=mm(a,a);
    }
}
bool isp(){
    if(P<=B)return !np[P];
    if(~P&1)return 0;
    for(int i=0;i<15;++i)if(!mr())return 0;
    return 1;
}
num gcd(num a,num b){return b?gcd(b,a%b):a;}
num abs(num x){return x>0?x:-x;}
void pollard_rho(num n){
    setP(n);
    if(isp()){
        fs[fp++]=n;
        return;
    }
    const int mod=4095;
    for(;;){
        num a,b,c,prod=mulRR(1);
        a=b=mulRR(rnd());
        c=mulRR(rnd());
        for(i64 ii=1,k=2;;){
            a=fix1(mul(a,a)+c);
            prod=mul(prod,abs(a-b));
            if(!prod){
                prod=abs(a-b);
                num g=gcd(P,mul(prod,1));
                if(g==n)break;
                if(g!=1){
                    qs[qp++]=g;
                    qs[qp++]=n/g;
                    return;
                }
            }
            if(++ii==k)k<<=1,b=a;
            if(!(ii&mod)){
                num g=gcd(P,mul(prod,1));
                if(g==n)break;
                if(g!=1){
                    qs[qp++]=g;
                    qs[qp++]=n/g;
                    return;
                }
            }
        }
    }
}
void factor(num x){
    for(int i=0;i<pp;++i){
        for(int p=ps[i];x%p==0;fs[fp++]=p,x/=p);
    }
    if(x>1)qs[qp++]=x;
    while(qp)pollard_rho(qs[--qp]);
    std::sort(fs,fs+fp);
    for(int i=0;i<fp;++i)pr(fs[i]);
}
void init(){
    for(int i=2;i<=B;++i){
        if(!np[i])ps[pp++]=i;
        for(int j=0;j<pp&&i*ps[j]<=B;++j){
            np[i*ps[j]]=1;
            if(i%ps[j]==0)break;
        }
    }
    for(int i=0;i<pp;++i){
        int p=ps[i],s=1;
        while(s<=B/p)s*=p;
        pps[i]=s;
    }
}
int main(){
    init();
    factor(read());
    return 0;
}
View Code

 

posted on 2018-01-14 01:23  nul  阅读(507)  评论(0编辑  收藏  举报