HDU 1211 (inverse element) extended Euclidean + fast power

题目链接
Problem Description
RSA is one of the most powerful methods to encrypt data. The RSA algorithm is described as follow:

choose two large integer p, q
calculate n = p * q, calculate F(n) = (p - 1) * (q - 1)
choose an integer e(1 < e < F(n)), making gcd(e, F(n)) = 1, e will be the public key
calculate d, making d * e mod F(n) = 1 mod F(n), and d will be the private key

You can encrypt data with this method :

C = E(m) = (m ^ e) mod n

When you want to decrypt data, use this method :

M = D(c ) = (c ^ d) mod n

Here, c is an integer ASCII value of a letter of cryptograph and m is an integer ASCII value of a letter of plain text.

Now given p, q, e and some cryptograph, your task is to “translate” the cryptograph into plain text.

Input
Each case will begin with four integers p, q, e, l followed by a line of cryptograph. The integers p, q, e, l will be in the range of 32-bit integer. The cryptograph consists of l integers separated by blanks.

Output
For each case, output the plain text in a single line. You may assume that the correct result of plain text are visualable ASCII letters, you should output them as visual letters with no blank between them.

Sample Input
101 103 7 11
7716 7746 7497 126 8486 4708 7746 623 7298 7357 3239

Sample Output
I-LOVE-ACM.

Question meaning:
According to the requirements of the RSA encryption algorithm, we can get the following information:

  1. n = p*q;
  2. F = (p-1)*(q-1);
  3. There is an integer e and F mutually exclusive;
  4. The calculation method of integer d is d*e % F = 1; (implemented by extended Euclidean)
  5. Need to ask m = c d mod n; (implemented with fast exponentiation)

Analysis:
First of all, we must understand what Extended Euclidean is. I will not repeat it here. There are many bloggers on the Internet who have analyzed it very well. Here I will simply talk about how to apply it to this topic.

We know that extended Euclid can find the solution of the linear equation ax+by=gcd(a, b) x and y;

We also need to know the definition of the inverse element, that is, ax = 1 mod n;

In this way, the linear equation can be modified to ax + by=1 under the premise of ensuring that a and b are mutually prime;

If both sides of the equation are modulo b at the same time, then you get
ax = 1 mod b (this is the inverse of a)

According to the "4" I mentioned in the question, the equation "d*e%F=1" is equivalently transformed into

e*d = 1 mod F, where e and F are relatively prime

Why do you ask for reciprocity? First introduce a Bezu theorem:

That is, if a and b are integers, then there must be integers x and y such that ax+by=gcd(a,b).

In other words, if ax+by=m has a solution, then m must be several times gcd(a,b). (You can judge whether such a formula has a solution)
There is a direct application that if ax+by=1 has a solution, then gcd(a,b)=1;

ps: In this article, I wrote an explanation about the extended Euclidean inverse element, and I think it’s okay.

In this way, we have found d, and the rest is the content of the fast power.

#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;

typedef long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);

ll Ext_gcd(ll a,ll b,ll &x,ll &y){
    
    
    if(b==0){
    
    
        x=1;
        y=0;
        return a;
    }
    ll ret=Ext_gcd(b,a%b,x,y);
    ll t = x;
    x = y;
    y=t-(a/b)*y;
    return ret;
}

ll Mul_Pow(ll a,ll b,ll mod){
    
    
    ll res=1;
    while(b>0){
    
    
        if(b&1)
            res = res * a % mod;
        a = a * a % mod;
        b>>=1;
    }
    return res;
}
int main()
{
    
    

    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    ll p,n,F,q,e,val,d,x,y,ans;
    int l;
    while(scanf("%lld%lld%lld%d",&p,&q,&e,&l)!=EOF){
    
    
        n = p*q;
        F = (p-1)*(q-1);
        d = Ext_gcd(e,F,x,y);
        d = (x%F+F)%F;//因为x有可能为负数

        for(int i=0;i<l;i++){
    
    
            scanf("%lld",&val);
            val = Mul_Pow(val,d,n);
            printf("%c",char(val));
        }
        printf("\n");
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/c___c18/article/details/115448643