POJ2447 分解因数+扩展欧几里得+高次幂取模

来源:互联网 发布:淘宝女士防晒帽 编辑:程序博客网 时间:2024/05/29 15:58

昨天一天弄明白的pollard-rho启发式因数分解没想到今天就用上了 而且是一次过 感觉好有成就感 

题目大意 给你N=P*Q 先把p q从N因数分解出来 得到具体的值 然后(p-1)*(q-1)=t 从而求出t的值

有了t的值 根据e*d(mod t)=1 求出e模t的逆元d 注意求出的逆元可能为负 然后求c^d%n 为m 就是

题目要求的值

这题的解题步骤如下

1根据pollard-rho启发式因数分解 把n分解成两个素数p q;

2(p-1)*(q-1)求出t的值

3通过扩展欧几里得 求e模t的逆元变换为 e*d+t*y=1 求出d的值 此时d可能为负 变成正值

4求出c^d%n 即为答案

最后要感谢GF陪我熬夜 鼓励刺激我让我的模板出的那么快。。。


#include <iostream>#include<cstdio>#include<cstdlib>using namespace std;typedef long long int64;int64 gcd(int64 a,int64 b){    if (a==0) return 1;    if(a<0) return gcd(-a,b);    if(b==0) return a;    return gcd(b,a%b);}int64 modmult(int64 a,int64 b,int64 n)//a*b%n{    a%=n;    int64 ret;    for(ret=0; b; a=(a<<1)%n,b>>=1)        if(b&1)            ret=(ret+a)%n;    return ret;}int64 modular(int64 a,int64 b,int64 n)//renturn a^b%n{    int64 ans=1;    a%=n;    while(b)    {        if(b&1)            ans=modmult(ans,a,n),b--;        b>>=1;        a=modmult(a,a,n);    }    return ans;}bool witness(int64 a,int64 n)//判断 a^(n-1)=1(mod n){    int t=0;    int64 x,xi,temp=n-1;    while(temp%2==0)        t++,temp/=2;    xi=x=modular(a,temp,n);    for(int i=1; i<=t; i++)    {        xi=modmult(xi,xi,n);        if(xi==1&&x!=1&&x!=n-1)            return 1;        x=xi;    }    if(xi!=1)        return 1;    return 0;}bool millar_rabin(int64 n,int s){    for(int j=1; j<=s; j++)    {        int64 a=rand()%(n-1)+1;//a=rand()%(Y-X+1)+X; /*n为X~Y之间的随机数        if(witness(a,n))            return 0;    }    return 1;}int64 pollard_rho(int64 n,int64 c){    int64 i=1,k=2,x,y;    x=rand()%n;    y=x;    while(1)    {        i++;        x=(modmult(x,x,n)+c)%n;        int64 d=gcd(y-x,n);        if(d!=1&&d!=n)            return d;        if(x==y)            return n;        if(i==k)        {            y=x;            k+=k;        }    }}int64 factor[100];int tol;void findfac(int64 n){    if(millar_rabin(n,10))    {        factor[tol++]=n;        return;    }    int64 p=n;    while(p>=n)        p=pollard_rho(p,rand()%(n-1)+1);    findfac(p);    findfac(n/p);}void exgcd(long long a,long long b,long long &d,long long &x,long long &y){    if(b==0)    {        x=1;        y=0;        d=a;        return;    }    else    {        exgcd(b,a%b,d,x,y);        long long temp=x;        x=y;        y=temp-(a/b)*y;    }}int main(){    long long c,e,n,d,t,gc,y,m;    while(~scanf("%lld%lld%lld",&c,&e,&n))    {        tol=0;        findfac(n);        t=(factor[0]-1)*(factor[1]-1);        exgcd(e,t,gc,d,y);        d=(d+t)%t;        m=modular(c,d,n);        printf("%lld\n",m);    }    return 0;}


原创粉丝点击