乘数密码 扩展欧几里得求逆元

来源:互联网 发布:绍兴用友软件 编辑:程序博客网 时间:2024/06/05 10:28

题目来源:http://acm.nyist.net/JudgeOnline/problem.php?pid=769

乘数密码

时间限制:1000 ms  |  内存限制:65535 KB
难度:1
 
描述

乘数密码也是一种替换密码,其加密变换是将明文字母串逐位乘以密钥k并进行模运算,数学表达式如下:

E(m)=k*m mod q,   gcd(k,q)=1 (即k,q互素)。

当k与q互素时,明文字母加密成密文字母的关系为一一映射。

现有一经过乘法加密的密文,请破译出它的明文。

 
输入
输入包含多组数据,不超过1000组。
每组包含一个字符串和一个正整数k,字符串全部由大写字母组成,长度不超过50,k是与q互素的数,q=26,k<26。
输出
每组输出数据单独占一行,输出对应的明文。
样例输入
ILOVEYOU 3
样例输出
UVWHKIWY

分析:
1:加密 E(m) = k*m % q 且 gcd(k,q)=1;
2:解密 m = E(m) * k^-1(mod q) mod q 。
k^-1(mod q)为 kx≡1(mod q)中 x 的值。 
代码如下:
#include<iostream>#include<stdlib.h>#include<stdio.h>#include<math.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<map>#define N 55using namespace std;char str[N];// 扩展欧几里得 , 得到 x, y, d等式 ax + by =dint extend_gcd(int a, int b, int&x, int &y){    if(b==0) {x=1; y=0; return a;}    int d=extend_gcd(b,a%b, y,x);    y-=a/b *x;}// **************求逆元 ,在 已知 gcd(k,n) =1 的情况// kx =1(mod n)int mod_reverse(int k, int n){    int x,y;    extend_gcd(k,n,x,y)%n;     return (x%n +n)%n;}int main(){    while(cin>>str)    {        int k;        scanf("%d",&k);        for(int i=0; i<strlen(str) ; i++)        {            str[i]  = (str[i] -'A') * mod_reverse(k,26) %26 +'A';            printf("%c",str[i]);        }        printf("\n");    }    return 0;}

 

 
 
0 0