bzoj 4522 [Cqoi2016]密钥破解

数论模板大综合。

用rho算法分解N,找出p,q,算出r=(p-1)(q-1)。

然后用拓展欧几里得求解e在模r意义下的逆元d。

最后快速幂求出c^d mod N。

基本按照题目描述做就好。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long LL;//long long
LL Multi(LL a,LL b,LL k)
{   LL ret=0;
    while(b)
      {if(b&1)ret=(ret+a)%k;
       a=(a+a)%k;b/=2;
      }
    return ret;
}
LL gcd(LL a,LL b)
{   if(!b)return a;
    else return gcd(b,a%b);
}
LL Abs(LL x)
{   if(x<0)x=-x;return x;}
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{   if(!b){d=a;x=1;y=0;}
    else
      {exgcd(b,a%b,d,x,y);
       LL t=x;x=y;y=t-(a/b)*x;
      }
}
LL QuickMi(LL b,LL p,LL k)
{   LL ret=1;
    while(p)
      {if(p&1)ret=Multi(ret,b,k);
       b=Multi(b,b,k);
       p/=2;
      }
    return ret;
}
int main()
{   srand(10007);
    LL e,N,c,r,p,q,QAQ=10007,x,y,i,k,D,d,bj=1;
    cin>>e>>N>>c;
    while(bj)
      {i=1;k=2;x=rand()%(N-1)+1;y=x;
       while(1)
         {i++;
          x=(Multi(x,x,N)+QAQ)%N;
          if(x==y)break;
          d=gcd(Abs(x-y),N);
          if(1<d&&d<N){p=d;q=N/d;bj=0;break;}
          if(i==k){y=x;k*=2;}
         }
       QAQ--;
      }
    r=(p-1)*(q-1);
    exgcd(e,r,D,x,y);
    d=(x%r+r)%r;
    cout<<d<<" "<<QuickMi(c,d,N);
    return 0;
}


你可能感兴趣的:(bzoj 4522 [Cqoi2016]密钥破解)