【题解】P5451 [THUPC2018]密码学第三次小作业

· · 题解

题意概括

实际上,题目背景和所求并没有很强的相关性,现摘录简化版题目要求:

现有相同的模数 N 与不同的私钥。设两公钥分别为 e_1,e_2\gcd(e_1,e_2)=1。明文消息为 m,密文分别为:

\begin{matrix}c_1=m^{e_1}\bmod N\\c_2=m^{e_2}\bmod N\end{matrix}

已知 c_1,c_2,e_1,e_2,N,求 m

寻找突破口

重点应该在 e_1,e_2 互质,也就是说 \gcd(e_1,e_2)=1,这是突破口。

于是我们可以发现应当有整数 s,t 使得下列式子成立:

s\cdot e_1+t\cdot e_2=\gcd(e_1,e_2)=1

我们发现,式子的右边是 1,这个 1 必须成为连接答案和题设的桥梁。如何让这个 1 把两者连接起来呢?一个比较朴素的想法是将 1m 相乘,但是这是徒劳的。

推导式子

我们会发现,在题目所给的式子中:

\begin{matrix}c_1=m^{e_1}\bmod N\\c_2=m^{e_2}\bmod N\end{matrix}
$$m\equiv m^1\equiv m^{s\cdot e_1+t\cdot e_2}\pmod N$$ 如果我们利用幂的性质,将指数上不大好处理的 $+$ 变成乘号,就能够得到一个式子: $$m\equiv m^{s\cdot e_1}\times m^{t\cdot e_2}\pmod N$$ 这时候我们注意到一件事情,在式子中独立出现了 $m^{e_1}$ 和 $m^{e_2}$,回归到题目所给的式子: > $$\begin{matrix}c_1=m^{e_1}\bmod N\\c_2=m^{e_2}\bmod N\end{matrix}$$ 我们会发现这里实际上可以进行一个替换,也就是说我们可以在模 $N$ 的意义下把 $m^{e_1}$ 和 $m^{e_2}$ 用 $c_1$ 和 $c_2$ 替换,得到了一个式子如下: : $$m \equiv c_1^sc_2^t \pmod N$$ ## 求解方法 对于题解开头的那个式子,我们可以很轻松地使用 $\rm Exgcd$ 求得 $s,t$ 的值,而现在的问题仅仅存在于答案的计算。我们很自然的会想到这是一个使用快速幂的好机会,但是我们不能想到一件事:如果 $s,t<0$ 怎么办? 其实还真的不难处理,我们只需要将 $s=-1\times -s$ 就行了,如果把它放在原来的式子当中(在模 $N$ 意义下讨论),就可以得到 $c^{-1}\times c^{-s}$。此时后半部分由于 $s$ 是负数,指数就是正数可以用快速幂计算,而前半部分只要在模 $N$ 意义下求取逆元即可,但是因为不可抗力不能使用 Fermat Little Theorem,于是你可以使用 Exgcd 求解。 记得要开 `long long`,并且有些点爆了还得单独特殊处理,由于处理不善,所以龟速乘部分采自神 GoPoux4 的代码,其余部分按照文章推导进行处理即可,具体见代码。 ## 代码实现 ```cpp #include<bits/stdc++.h> #define int long long using namespace std; int c1,c2,e1,e2,N,T; int gsc(int a,int b){ int ans=0; while(b>0){ if(b&1) ans=(ans+a)%N; a=(a+a)%N; b>>=1; }return ans; }int ksm(int a,int b){ int ans=1; a%=N; while(b>0){ if(b&1)ans=gsc(ans,a); a=gsc(a,a); b>>=1; }return ans%N; }int exgcd(int a,int b,int &x,int &y){ if(!b) {x=1,y=0;return a;} int k=exgcd(b,a%b,x,y); int z=x;x=y,y=z-a/b*y; return k; }int inv(int a,int b){ int x,y; int g=exgcd(a,b,x,y); return g==1?(x%b+b)%b:-1; }signed main(){ cin>>T; while(T--){ cin>>c1>>c2>>e1>>e2>>N; int s,t,g=exgcd(e1,e2,s,t); if(s<0)c1=inv(c1,N),s=-s; if(t<0)c2=inv(c2,N),t=-t; cout<<gsc(ksm(c1,s),ksm(c2,t))<<endl; }return 0; } ```