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\n");
        else printf("%lld\n",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\n");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\n");
    else if(top==1){
        int cnt=0;
        while(n%st[top]==0)n/=st[top],cnt++;
        if(cnt==3)printf("%lld %lld %lld\n",st[top],st[top]*st[top],st[top]*st[top]*st[top]);
        else printf("is not a D_num\n");
    }else if(top==2){
        if(n==st[1]*st[2])printf("%lld %lld %lld\n",st[1],st[2],st[1]*st[2]);
        else printf("is not a D_num\n");
    }return;
}

int main(){
    while(scanf("%lld",&n)==1){
        if(n==1){printf("is not a D_num\n");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\n");
		else printf("%lld\n",mn);
	}return 0;
}

  

时间: 2024-10-10 04:56:21

pollard_rho 学习总结 Miller_Rabbin 复习总结的相关文章

免费送2016高中学习资料同步复习资料

[历年+模拟试题分类汇编][发布800份]没拿到的速度了[大家在qq客户端,手机qq,和我聊天的地方回复"资料"两个字,完成任务,就能够拿到资料了.资料每天分享.]每天送学习资料 加入易梦网校+学习系统请联系客服QQ:1517757127 还送学习视频.拿到资料的后,不会解压的同学联系技术Q:1517757127,帮你解压!!! 本信息由SKYCC组合营销软件发出.

Android学习之多线程复习——倒计时

今天周六,离职在家,复习了一下多线程的一些知识 然后写了一个简单的倒计时程序: 以下是我的activity_main的布局文件: 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent&q

模拟I2C协议学习点滴之复习三极管、场效应管;场效应管漏极开门电路

晶体三极管分为NPN和PNP型两种结构形式,除了电源极性的不同工作原理是大致相同的.对于NPN管,它是由2块N型半导体夹着一块P型半导体所组成的,发射区与基区之间形成的PN结称为发射结,而集电区与基区所形成的PN结称为集电结,三条引线分别为发射极(Emitter).基极(Base)和集电极c(Collector).b点电压高于e点电压时,发射结正偏,而当c点电压高于b点电压时,集电结反偏,集电结电源要高于基极电源.由于在制造过程中,发射区的自由电子浓度要多于集电区的电子浓度,因此在正偏电压下,自

Android学习:Toast复习总结

        Toast.makeText(this.getApplication(), "hello toast^^^^^^", 1).show(); 1特点: (1)没有焦点 (2)显示的时间有限,会自动消失. 2:参数说明: 第一个参数:应用的上下文Context Context提供了关于应用环境全局信息的接口.它是一个抽象类,它的实现由 Android系统所提供.通过context我们可以加载资源,获取由android提供的一些 服务类. 在Android当中一般有两种con

linux学习——第二周复习

原文地址:https://www.cnblogs.com/it-ljm1903/p/10712555.html

mybatis框架学习-前置,复习Jdbc

Jdbc需要一个数据库驱动包:mysql-connector-java.jar 然后需要用到的类一般有 Connecto:数据库连接 PrepareStatement(或者Statement):用于执行sql语句 ResultSet:数据库操作返回的结果 以下个人案例:从数据库中查找id = 1的用户信息 1.前期mysql准备 create database cong use cong; create table account( id int primary key auto_increme

我的python学习--第四天

一.首先是对前三天的学习内容进行复习 1.python基础的数据结构 数字(int/float,包括整数和浮点数) 布尔(boolean => True/False) 字符串(str,使用''或""括起来) 列表(list) 列表是使用[]括起来的一组数组,在内存中是连续的,可以对其增删改查 字典(dict) 字典是使用{}括起来的k/v键值对,经过哈希计算随机分布在内存中,是无序的,可以对其增删改查 元组(tuple) 元组与列表类似,不同之处在于元组的元素不能修改,元组使用小

2015年下半年网规考试预测(复习参考和交流)

考试在下半年11月份进行,网络安全防范内容可能占较大比重,预测内容如下,仅供大家学习交流和复习参考: 1.上午题:可能涉及网络通信规范.Linux系统知识.IP地址转换换算及子网掩码.IPV6.路由器协议.交换机连接.VPN技术.防火墙技术.网络病毒.网络漏洞攻击.ARP攻击.密钥认证等. 2.下午案例问答题:可能涉及互联网数据中心(数据库的设备配置,如服务器.冗余设计等安全措施:数据库的优化:流量监控等).Lan-to-Lan VPN.SaaS公司级服务.Named Data Networki

Java学习笔记day_01

Java学习笔记(复习整理) 虽然不知道该怎么写,但是不起步就永远不知道该怎么做..刚开始可能会写的很差劲,但会一点一点变好的. 本笔记是以我按照传智播客的视频和Java核心思想来学习,前面的基础部分主要是用于个人的复习使用的. 第一段代码:HelloWorld public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World"); } }