pollard_rho(大数质因子分解)

大佬博客
运用大素数判断和随机化算法来找寻一个因子,而可以递归求出所有的因子。
poj 1811
题意:判断一个数是不是素数,是的话输出prime否则的话输出这个数的最小素因子。

#include<cstdio>
#include<cstring>
#include<ctime>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e6+10;
int cont;
LL factor[200];//分解结果(返回结果是无序的)
static int S=3;//规定随机多少次,次数越多正确率越高
LL quick_mod_multi(LL a,LL b,LL mod)//快速求a*b%mod
{
    LL t=0;
    a%=mod;
    while(b)
    {
        if(b&1)
        {
            t+=a;
            if(t>=mod)//取模要比减法慢的多
                t-=mod;
        }
        a<<=1;
        if(a>=mod) a-=mod;
        b>>=1;
    }
    return t;
}
LL quick_mod_power(LL a,LL b,LL mod)//快速求a^b%mod
{
    LL res=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            res=quick_mod_multi(res,a,mod);
        b>>=1;
        a=quick_mod_multi(a,a,mod);
    }
    return res;
}
bool miller_rabbin(LL n)//素性检验
{
    if(n==2) return true;
    if(n<2||!(n&1)) return false;
    int t=0;
    LL a,x,y,u=n-1;
    while((u&1)==0) t++,u>>=1;
    for(int i=0; i<S; i++) //随机多少次
    {
        a=rand()%(n-1)+1;
        x=quick_mod_power(a,u,n);
        for(int j=0; j<t; j++)
        {
            y=quick_mod_multi(x,x,n);
            if(y==1&&x!=1&&x!=n-1)
                return false;
            x=y;
        }
        if(x!=1) return false;
    }
    return true;
}
LL get_gcd(LL a,LL b)
{
    if(a==0) return 1;
    if(a<0) return get_gcd(-a,b);
    while(b)
    {
        LL t=a%b;
        a=b;
        b=t;
    }
    return a;
}
LL pollard_rho(LL n,LL c)
{
    LL i=1,k=2,x,y;
    x=rand()%n;
    y=x;
    while(1)
    {
        i++;
        x=(quick_mod_multi(x,x,n)+c)%n;
        LL d=get_gcd(y-x,n);
        if(d>1&&d<n) return d;
        if(y==x) return n;
        if(i==k)
        {
            y=x;
            k<<=1;
        }
    }
}
void findfac(LL n)//找n的素因子
{
    if(n==1) return ;
    if(miller_rabbin(n))
    {
        factor[cont++]=n;
        return ;
    }
    LL p=n;
    while(p>=n)
        p=pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}
int main()
{
    srand((unsigned)time(NULL));//poj 上有这个会RE
    int ncase;
    scanf("%d",&ncase);
    while(ncase--)
    {
        LL n;
        scanf("%lld",&n);
        if(miller_rabbin(n)) printf("Prime\n");
        else
        {
            cont=0;
            findfac(n);
            LL ans=factor[0];
            for(int i=0; i<cont; i++)
                ans=min(ans,factor[i]);
            printf("%lld\n",ans);
        }
    }
}

hdu 4344
题意:给出一个长为n(n小于2^63)的管子,现在要在管子上做标记,每隔L个长度单位做一个标记,从管子头端开始,保证最后一次标记恰好在管子的尾端。让你找出有多少个这样的L(n>L),且他们之间两两互素,然后求出这些L的和最大值。
思路:首先可以想到L肯定是n的因子,还要所有互素的因子,只需要找到所有的素因子,统计一下相同的素因子有多少个,假如有k个则不相同的素因子的k次方肯定是互素的,加起来就好了。还要注意只有一个因子的时候这个时候k次幂就是自己本身,所以求的是k-1次幂;

#include<cstdio>
#include<cstring>
#include<ctime>
#include<map>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e6+10;
int cont;
LL factor[200];//分解结果(返回结果是无序的)
static int S=3;//规定随机多少次,次数越多正确率越高
LL quick_mod_multi(LL a,LL b,LL mod)//快速求a*b%mod
{
    LL t=0;
    a%=mod;
    while(b)
    {
        if(b&1)
        {
            t+=a;
            if(t>=mod)//取模要比减法慢的多
                t-=mod;
        }
        a<<=1;
        if(a>=mod) a-=mod;
        b>>=1;
    }
    return t;
}
LL quick_mod_power(LL a,LL b,LL mod)//快速求a^b%mod
{
    LL res=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            res=quick_mod_multi(res,a,mod);
        b>>=1;
        a=quick_mod_multi(a,a,mod);
    }
    return res;
}
bool miller_rabbin(LL n)//素性检验
{
    if(n==2) return true;
    if(n<2||!(n&1)) return false;
    int t=0;
    LL a,x,y,u=n-1;
    while((u&1)==0) t++,u>>=1;
    for(int i=0; i<S; i++) //随机多少次
    {
        a=rand()%(n-1)+1;
        x=quick_mod_power(a,u,n);
        for(int j=0; j<t; j++)
        {
            y=quick_mod_multi(x,x,n);
            if(y==1&&x!=1&&x!=n-1)
                return false;
            x=y;
        }
        if(x!=1) return false;
    }
    return true;
}
LL get_gcd(LL a,LL b)
{
    if(a==0) return 1;
    if(a<0) return get_gcd(-a,b);
    while(b)
    {
        LL t=a%b;
        a=b;
        b=t;
    }
    return a;
}
LL pollard_rho(LL n,LL c)
{
    LL i=1,k=2,x,y;
    x=rand()%n;
    y=x;
    while(1)
    {
        i++;
        x=(quick_mod_multi(x,x,n)+c)%n;
        LL d=get_gcd(y-x,n);
        if(d>1&&d<n) return d;
        if(y==x) return n;
        if(i==k)
        {
            y=x;
            k<<=1;
        }
    }
}
void findfac(LL n)//找n的素因子
{
    if(n==1) return ;
    if(miller_rabbin(n))
    {
        factor[cont++]=n;
        return ;
    }
    LL p=n;
    while(p>=n)
        p=pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}
int main()
{
    srand((unsigned)time(NULL));
    int ncase;
    scanf("%d",&ncase);
    while(ncase--)
    {
        LL n;
        scanf("%lld",&n);
        if(miller_rabbin(n)) printf("Prime\n");
        else
        {
            cont=0;
            findfac(n);
            map<LL,LL> mp;
            for(int i=0; i<cont; i++)
            {
                if(mp[factor[i]]==0)
                    mp[factor[i]]=factor[i];
                else
                    mp[factor[i]]*=factor[i];
            }
            LL ans=0;
            map<LL,LL>::iterator it;
            for(it=mp.begin(); it!=mp.end(); it++)
                ans+=(it->second);
            if(mp.size()==1)
                ans/=factor[0];
            printf("%d %lld\n",mp.size(),ans);
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA解密算法是非常复杂的,包含了多个步骤和计算,需要涉及到大数运算、密钥生成、加密和解密等多个方面。以下是一个简单的示例,仅供参考: ```python from math import gcd from Crypto.Util.number import inverse # 定义素性测试算法 def is_prime(n): if n <= 1: return False elif n <= 3: return True elif n % 2 == 0 or n % 3 == 0: return False i = 5 while i ** 2 <= n: if n % i == 0 or n % (i + 2) == 0: return False i += 6 return True # 定义大数质因子分解算法 def pollard_rho(n): i = 0 x = randint(0, n - 1) y = x k = 2 while True: i += 1 x = (x ** 2 - 1) % n d = gcd(y - x, n) if d != 1 and d != n: return d if i == k: y = x k *= 2 def factorize(n): factors = [] while n > 1: factor = pollard_rho(n) factors.append(factor) n //= factor return factors # 定义RSA解密算法 def rsa_decrypt(ciphertext, n, d): plaintext = pow(ciphertext, d, n) return plaintext # 生成密钥对 def generate_key_pair(p, q): n = p * q phi = (p - 1) * (q - 1) e = 65537 d = inverse(e, phi) return (n, e), (n, d) # 测试数据 p = 104729 q = 104717 n, e = generate_key_pair(p, q)[0] d = inverse(e, (p - 1) * (q - 1)) ciphertext = pow(123456, e, n) # 解密 plaintext = rsa_decrypt(ciphertext, n, d) print('p =', p) print('q =', q) print('n =', n) print('e =', e) print('d =', d) print('ciphertext =', ciphertext) print('plaintext =', plaintext) ``` 需要注意的是,以上代码仅作为算法示例,可能存在性能瓶颈和不足之处,仅供参考。如果你需要更加详细和完善的算法实现,建议查阅相关的数学和计算机科学文献,并在专业人士指导下进行实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值