• pollard_rho 学习总结 Miller_Rabbin 复习总结


    吐槽一下名字,泼辣的肉。。OwO

    我们知道分解出一个整数的所有质因子是O(sqrt(n)/ln(n))的

    但是当n=10^18的时候就显得非常无力的

    这个算法可以在大概O(n^(1/4))的时间复杂度的情况下把n分解成p*q

    递归分解就可以得到质因子了,跑得非常快

    做法是这样的,考虑利用生日悖论

    设范围为[1,365]的正整数

    设集合{x1,x2……,xk}当k大概到58时

    那么这个集合中存在两个数相等的概率几乎为99%

    那么相应的对于一个数n,我们随机一个集合,这个集合中任取两个数x,y,gcd(abs(x-y),n)不为1的概率也是很大的

    但是集合中两两枚举判断是很麻烦的,所以我们可以考虑迭代求解

    通常情况下利用f(x)=(x*x+c)%n来迭代生成伪随机数

    之后做法有两种,一种是每次迭代并判断(x,f(x))是否是满足条件的(x,y)对

    这个做法的缺点是因为f函数存在f环,所以很容易陷入死循环,所以需要写floyd判圈算法

    如果存在环直接跳出重新随机x和c

    第二种做法是固定一个y,之后利用函数迭代生成x并判断

    然后定期随机一个y,gcd为n时跳出,然后反复多次随机x和c即可

    第二种做法写起来比较简单,但是貌似没有第一种快

    Miller_Rabbin算法是用来判断一个数是否是素数的

    判断标准有两个:

    1、随机基底a,若a^(p-1)%p!=1,则p一定不是素数,否则可能是

    2、若x^2%p=1的解除了p-1和1外还有别的,则p一定不是素数,否则可能是

    对于第二个条件的判断是把p-1表示成q*2^s的形式

    然后再判断第一个条件做平方的时候顺便判断一下第二个

    一次失败概率大概是(1/4)左右,随机若干次判断即可

    QAQ 昨天只用第一种判断方式WA的我不省人事 QAQ

    刷了一些模板题,发现边界各种醉

    BZOJ 3667 

    裸模板题,注意质数判断要两个条件一起用

    然后要写O(1)快速乘,不然会T

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    typedef long long LL;
    int T;
    LL n,mx;
     
    LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
    LL mul_mod(LL a,LL b,LL p){  
        a%=p;b%=p;  
        LL t=(a*b-(LL)((double)a/p*b+0.5)*p);  
        return t<0?t+p:t;  
    }  
    LL pow_mod(LL v,LL p,LL mod){
        LL tmp=1;
        while(p){
            if(p&1)tmp=mul_mod(tmp,v,mod);
            v=mul_mod(v,v,mod);p>>=1;
        }return tmp;
    }
    bool Get_judge(LL v,LL mod,LL p,LL s){
        v=pow_mod(v,p,mod);
        for(LL i=1,now=v;i<=s;++i){
            v=mul_mod(v,v,mod);
            if(v==1&&now!=1&&now!=mod-1)return true;
            now=v;
        }return v!=1;
    }
    bool Get_check(LL n){
        if(n==2||n==3)return true;
        if(n%2==0)return false;
        if(n%3==0)return false;
        LL p=n-1,s=0;
        while(!(p&1))p>>=1,s++;
        for(int i=0;i<10;++i)if(Get_judge(rand()%(n-2)+1,n,p,s))return false;
        return true;
    }
    LL Get_FJ(LL n,LL c){
        LL k=2,x=rand()%n,y=x,p=1;
        for(LL i=1;p==1;++i){
            x=(mul_mod(x,x,n)+c)%n;
            p=gcd(abs(x-y),n);
            if(i==k)y=x,k<<=1;
        }return p;
    }
    void Get_ans(LL n){
        if(n==1)return;
        if(Get_check(n)){mx=max(mx,n);return;}
        LL tmp=n;
        while(tmp==n)tmp=Get_FJ(n,rand()%(n-2)+1);
        Get_ans(tmp);Get_ans(n/tmp);    
    }
     
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%lld",&n);
            mx=0;Get_ans(n);
            if(mx==n)printf("Prime
    ");
            else printf("%lld
    ",mx);
        }return 0;
    }
    
    

    BZOJ 4522 CQOI 密钥破解

    直接按照题意模拟即可

    先用泼辣的肉分解,然后ex_gcd,最后快速幂

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
     
    typedef long long LL;
    LL e,N,c,p,q,r;
    LL d,x,y;
     
    LL mul_mod(LL a,LL b,LL mod){
        LL s=0;
        while(b){
            if(b&1)s=(s+a)%mod;
            a=(a<<1)%mod;b>>=1;
        }return s;
    }
    LL pow_mod(LL v,LL p,LL mod){
        LL tmp=1;
        while(p){
            if(p&1)tmp=mul_mod(tmp,v,mod);
            v=mul_mod(v,v,mod);p>>=1;
        }return tmp;
    }
    LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
    void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){
        if(b==0){d=a;x=1;y=0;}
        else{ex_gcd(b,a%b,d,y,x);y-=(a/b)*x;}
    }
    LL Get_FJ(LL n,LL c){
        LL k=2,x=rand()%n,y=x,p=1;
        for(LL i=1;p==1;++i){
            x=(mul_mod(x,x,n)+c)%n;
            p=gcd(abs(x-y),n);
            if(i==k)y=x,k<<=1;
        }return p;
    }
     
    int main(){
        scanf("%lld%lld%lld",&e,&N,&c);
        p=N;
        while(p==N)p=Get_FJ(N,rand()%(N-2)+1);
        q=N/p;r=(p-1)*(q-1);
        ex_gcd(e,r,d,x,y);d=r/d;
        x=(x%d+d)%d;
        y=pow_mod(c,x,N);
        printf("%lld %lld",x,y);
        return 0;
    }
    
    

    hdu 4344

    分解出所有质因数

    直接上模板,注意看题目要求就可以了

    (N>L)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    
    typedef unsigned long long LL;
    int T,top=0;
    LL st[1010];
    LL n,ans;
    
    LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
    LL mul_mod(LL a,LL b,LL mod){
        LL s=0;
        while(b){
            if(b&1)s=(s+a)%mod;
            a=(a<<1)%mod;b>>=1;
        }return s;
    }
    LL pow_mod(LL v,LL p,LL mod){
        LL tmp=1;
        while(p){
            if(p&1)tmp=mul_mod(tmp,v,mod);
            v=mul_mod(v,v,mod);p>>=1;
        }return tmp;
    }
    bool Get_judge(LL v,LL mod,LL p,LL s){
        v=pow_mod(v,p,mod);
        for(LL i=1,now=v;i<=s;++i){
            v=mul_mod(v,v,mod);
            if(v==1&&now!=mod-1&&now!=1)return true;
            now=v;
        }return v!=1;
    }
    bool Get_check(LL n){
        if(n==2||n==3)return true;
        if(n%2==0||n%3==0)return false;
        LL p=n-1,s=0;
        while(!(p&1))p>>=1,s++;
        for(int i=0;i<10;++i)if(Get_judge(rand()%(n-2)+1,n,p,s))return false;
        return true;
    }
    LL Get_FJ(LL n,LL c){
        LL k=2,x=rand()%n,y=x,p=1;
        for(LL i=1;p==1;++i){
            x=(mul_mod(x,x,n)+c)%n;
            p=gcd(x<=y?y-x:x-y,n);
            if(i==k)y=x,k<<=1;
        }return p;
    }
    void Get_ans(LL n){
        if(n==1)return;
        if(Get_check(n)){st[++top]=n;return;}
        LL tmp=n;
        while(tmp==n)tmp=Get_FJ(n,rand()%(n-2)+1);
        Get_ans(tmp);Get_ans(n/tmp);
    }
    
    int main(){
        srand(110);
        scanf("%d",&T);
        while(T--){
            cin>>n;top=0;
            if(n==1){printf("1 1
    ");continue;}
            Get_ans(n);ans=0;
            sort(st+1,st+top+1);
            top=unique(st+1,st+top+1)-st-1;
            printf("%d ",top);
            for(int i=1;i<=top;++i){
                LL now=1;
                while(n%st[i]==0)n/=st[i],now*=st[i];
                ans+=now;
            }
            if(top==1)ans/=st[top];
            cout<<ans<<endl;
        }return 0;
    }
    

    hdu 3864

    分解之后分类讨论一下

    注意n=p^3这种情况

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    int top=0;
    LL n;
    LL st[1010];
    
    LL mul_mod(LL a,LL b,LL mod){
        LL s=0;
        while(b){
            if(b&1)s=(s+a)%mod;
            a=(a<<1)%mod;b>>=1;
        }return s;
    }
    LL pow_mod(LL v,LL p,LL mod){
        LL tmp=1;
        while(p){
            if(p&1)tmp=mul_mod(tmp,v,mod);
            v=mul_mod(v,v,mod);p>>=1;
        }return tmp;
    }
    LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
    LL Get_FJ(LL n,LL c){
        LL k=2,x=rand()%n,y=x,p=1;
        for(LL i=1;p==1;++i){
            x=(mul_mod(x,x,n)+c)%n;
            p=gcd(abs(x-y),n);
            if(i==k)y=x,k<<=1;
        }return p;
    }
    bool Get_judge(LL v,LL mod,LL p,LL s){
        v=pow_mod(v,p,mod);
        for(LL i=1,now=v;i<=s;++i){
            v=mul_mod(v,v,mod);
            if(v==1&&now!=mod-1&&now!=1)return true;
            now=v;
        }
        return v!=1;
    }
    bool Get_check(LL n){
        if(n==2||n==3)return true;
        if(n%2==0||n%3==0)return false;
        LL p=n-1,s=0;
        while(!(p&1))p>>=1,s++;
        for(int i=0;i<10;++i)if(Get_judge(rand()%(n-1)+1,n,p,s))return false;
        return true;
    }
    void Get_ans(LL n){
        if(n==1)return;
        if(Get_check(n)){st[++top]=n;return;}
        LL tmp=n;
        while(tmp==n)tmp=Get_FJ(n,rand()%(n-1)+1);
        Get_ans(tmp);Get_ans(n/tmp);
    }
    void Get_print(){
        if(top>=3)printf("is not a D_num
    ");
        else if(top==1){
            int cnt=0;
            while(n%st[top]==0)n/=st[top],cnt++;
            if(cnt==3)printf("%lld %lld %lld
    ",st[top],st[top]*st[top],st[top]*st[top]*st[top]);
            else printf("is not a D_num
    ");
        }else if(top==2){
            if(n==st[1]*st[2])printf("%lld %lld %lld
    ",st[1],st[2],st[1]*st[2]);
            else printf("is not a D_num
    ");
        }return;
    }
    
    int main(){
        while(scanf("%lld",&n)==1){
            if(n==1){printf("is not a D_num
    ");continue;}
            top=0;Get_ans(n);
            sort(st+1,st+top+1);
            top=unique(st+1,st+top+1)-st-1;
            Get_print();
        }return 0;
    }
    

    poj 1811

    裸题,注意要交G++

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const LL oo=1LL<<60;
    int T;
    LL n,mn;
    
    LL mul_mod(LL a,LL b,LL mod){
    	LL s=0;
    	while(b){
    		if(b&1)s=(s+a)%mod;
    		a=(a<<1)%mod;b>>=1;
    	}return s;
    }
    LL pow_mod(LL v,LL p,LL mod){
    	LL tmp=1;
    	while(p){
    		if(p&1)tmp=mul_mod(tmp,v,mod);
    		v=mul_mod(v,v,mod);p>>=1;
    	}return tmp;
    }
    LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
    LL Get_FJ(LL n,LL c){
    	LL k=2,x=rand()%n,y=x,p=1;
    	for(LL i=1;p==1;++i){
    		x=(mul_mod(x,x,n)+c)%n;
    		p=gcd(x<=y?y-x:x-y,n);
    		if(i==k)y=x,k<<=1;
    	}return p;
    }
    bool Get_judge(LL v,LL mod,LL p,LL s){
    	v=pow_mod(v,p,mod);
    	for(LL i=1,now=v;i<=s;++i){
    		v=mul_mod(v,v,mod);
    		if(v==1&&now!=1&&now!=mod-1)return true;
    		now=v;
    	}return v!=1;
    }
    bool Get_check(LL n){
    	if(n==2||n==3)return true;
    	if(n%2==0||n%3==0)return false;
    	LL p=n-1,s=0;
    	while(!(p&1))p>>=1,s++;
    	for(int i=0;i<20;++i)if(Get_judge(rand()%(n-1)+1,n,p,s))return false;
    	return true;
    }
    void Get_ans(LL n){
    	if(n==1)return;
    	if(Get_check(n)){mn=min(mn,n);return;}
    	LL tmp=n;
    	while(tmp==n)tmp=Get_FJ(n,rand()%(n-1)+1);
    	Get_ans(tmp);Get_ans(n/tmp);
    }
    
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%lld",&n);
    		mn=oo;Get_ans(n);
    		if(mn==n)printf("Prime
    ");
    		else printf("%lld
    ",mn);
    	}return 0;
    }
    

      

  • 相关阅读:
    简单工厂模式实例
    浅析面向对象和面向过程
    equals与“==”的区别
    IIS挂起网站配置文件地址
    先安装win7时IIS的安装
    验证码的使用
    c#引用命名空间的作用
    ADO与ADO.NET的区别
    常用的数据库访问方式
    Exercise 11: Asking Questions
  • 原文地址:https://www.cnblogs.com/joyouth/p/5645719.html
Copyright © 2020-2023  润新知