题目来源: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 55 using namespace std; char str[N]; // 扩展欧几里得 , 得到 x, y, d等式 ax + by =d int 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; }