洛谷$P$4358密钥破解 $[CQOI2016]$ 数论

正解:数论

解题报告:

先,放个传送门$ QwQ $

这题难点可能在理解题意,,,

所以我先放个题意$QAQ$

大概就是说,给定一个整数$N$,可以被拆成两个质数的成绩$p\cdot q$,然后给出了一个数$e$,求$d$满足$e\cdot d\equiv 1 (mod\ r)$,其中$ r = ( p - 1 )\cdot ( q - 1 ) $,最后还会给定一个 $ c $ ,求$ d^{c}\ mod\ N$

$umm$就是几个板子题的堆砌昂,,,首先$pollard\ rho$找到$p\ q$求出$r$,然后逆元求出$d$,最后快速幂走一波

然后就做完辣!$over$!

然后这里注意一下,就我个人的习惯的话我很喜欢快速幂求逆元,,,因为很简单很无脑,,,但是这道题因为不保证互质所以不能用快速幂,只能用$exgcd$

另,有一个关于卡时限的小发现,首先显然龟速乘是真的很慢嘛,但是我发现,好像用$long\ double$乘比$int128$乘要慢,,,我也布吉岛为什么$QAQ$反正好像是这样儿的以后打的时候可以注意下$QAQ$

然后就麻油辣?放个代码$QwQ$

// luogu-judger-enable-o2
#include
using namespace std;
#define il inline
#define ll __int128
#define gc getchar()
#define rl register ll
#define rc register char
#define rb register bool
#define rp(i,x,y) for(rl i=x;i<=y;++i)

ll e,n,c,p,q,d,r;

il ll read()
{
    rc ch=gc;rl x=0;rb y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il ll gcd(rl gd,rl gs){return !gs?gd:gcd(gs,gd%gs);}
il ll multi(rl gd,rl gs,rl mod){return 1ll*gd*gs%mod;}//{rl tmp=((long double)gd/mod*gs+1e-8)*mod;return gd*gs-tmp<0?gd*gs-tmp+mod:gd*gs-tmp;}
il ll rrand(){return 1ll*rand()<<15^rand();}
il ll randd(){return 1ll*rrand()<<30^rrand();}
il ll power(rl x,rl y,rl mod){rl ret=1;while(y){if(y&1)ret=ret*x%mod;x=x*x%mod;y>>=1;}return ret;}
il bool miller_rabin(rl x)
{
    if(x==2 || x==3 || x==5)return true;
    if(x%2==0 || x%3==0 || x%5==0)return false;
    rp(i,1,6)
    {
        rl gdgs=rand()%(x-2)+2;if(power(gdgs,x-1,x)!=1)return false;rl poww=x-1;
        while(!(poww&1))
        {
            poww>>=1;
            rl tmp=power(gdgs,poww,x);
            if(multi(tmp,tmp,x)==1 && tmp!=1 && tmp!=x-1)return false;
        }
    }
    return true;
}
il ll pollard_rho(rl x)
{
    if(!(x%2))return 2;if(!(x%3))return 3;
    rl gs=randd()%x,tmp=randd()%x,gd=(multi(gs,gs,x)+tmp)%x,tim=0,timlim=2;
    while(1)
    {
        ++tim;gd=(multi(gd,gd,x)+tmp)%x;
        rl gcdd=gcd((gd-gs+x)%x,x);
        if(gd==gs || !tmp)return x;if(gcdd!=1 && gcdd!=x)return gcdd;if(!(tim^timlim))timlim<<=1,gs=gd;
    }
}
void exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return;}exgcd(b,a%b,y,x);y-=a/b*x;}
il ll inv(rl a,rl b){rl x,y;exgcd(a,b,x,y);return (x%b+b)%b;}
int main()
{
//     freopen("4358.in","r",stdin);freopen("4358.out","w",stdout);
    srand(time(NULL));
    e=read(),n=read(),c=read();
    p=pollard_rho(n);while(!miller_rabin(p))p=pollard_rho(n);q=n/p;r=(p-1)*(q-1);
//    printf("p=%lld r=%lld q=%lld ???=%lld ???=%lld ???=%lld\n",p,r,q,(p-1)*(q-1),p-1,q-1);
    d=inv(e,r);printf("%lld ",d);printf("%lld\n",power(c,d,n));
    return 0;
}
View Code 

你可能感兴趣的:(洛谷$P$4358密钥破解 $[CQOI2016]$ 数论)