查看附件:ios
他说答案是八位的大写字母,大写字母要么是ASCII表上的65-90,要么就0-25(或1-26)也是能够表示。可是既然说明是八位,那这个八位确定要体现出来,也就是说这个附件要可以搞出八个数码来表明大写字母。咱们先获得这个字符串的长度:34,这不能被8整除,那是否有别的字符能标识8段呢?
因而我写了这样一个程序:算法
#include <iostream> #include <map> #include <string> using namespace std; int main() { map<char, int> mp; string str = "8842101220480224404014224202480122"; for (int i = 0; i < (int)str.length(); ++i) mp[str[i]]++; for (map<char, int>::iterator it = mp.begin(); mp.end() != it; ++it) cout << it->first << ' ' << it->second << endl; return 0; }
结果以下:
首先咱们知道,要把一段序列分红8段,就必须某个字符要出现7次,这里出现7次的惟独’0’这个字符,那咱们就不妨以0为分界线来划分出8个数字码:
合起来就是:
WELLDONE(翻译就是干得漂亮?作得很好?)以为还像那么回事,因而提交!果真AC!markdown
下载附件:
说实话,我喜欢作这种题,由于我自己是作公钥密码学大类的(如今密码学研究都是公钥密码甚至是同态密码,前几道对称密码我不太了解……)ide
首先拿到素数p和q,而后计算n = p * q,phi(n) = (p - 1) * (q - 1)(欧拉函数,不晓得请自行了解),而后已知公钥e = 17,能够计算私钥d = e^(-1) mod( phi(n) )
也就是说,公钥和私钥互为逆元,这里要咱们求私钥d,至关于求逆元!如何求逆元?函数
能够用快速幂求逆元,固然也能够用拓展欧几里得算法求逆元,咱们就讲一种比较简单的方法求逆元。已知逆元的定义:
a * b mod p = 1
咱们就说:a和b互为模p意义下的逆元
由费马小定理获得:a^(p - 1) mod p = 1,那也就是说a * a^(p - 2) modp = 1,也就是说求a在模p意义下的逆元,就是求 a ^(p - 2)atom
可是这个方法的使用是有条件的!那就是p是素数,且a < p,而我们这个题,p是素数吗?模数不是素数,其实在RSA算法中,模数都不会是素数,由于p和q是不相同的素数,素数惟一的偶数是2,而p和q之中至少有一个不是2,则是奇数,那么p(或者q) - 1 就必定是偶数,偶数乘以任何数都是偶数,则必然模数不是质数!!加密
为何能够用扩展欧几里得算法呢?
先来看一个方程:
ax + by = 1
若是两边同时对b取模,则:ax mod b = 1
那么a和x就是模b意义下的逆元,而咱们告知a和b,求出x至关于求方程的解,由此能够得出用拓展欧几里得算法求逆元!spa
代码以下:翻译
#include <iostream> #define LL long long using namespace std; void extendGcd(LL a, LL b, LL& x, LL& y) { if (0 == b) { x = 1, y = 0; return; } extendGcd(b, a % b, x, y); LL Temp = x; x = y; y = Temp - (a / b) * y; } int main() { LL p = 473398607161, q = 4511491, e = 17; LL phi = (p - 1) * (q - 1); LL x, y; extendGcd(e, phi, x, y); cout << x; return 0; }
结果展现:3d
扩展欧几里得算法和费马小定理求逆元,是两种最多见的求逆元方法,此外还有筛法、递推等等办法,不过基本上,用拓展欧几里得就差很少能够搞定所有了!求逆元是数论、密码学中常见的计算需求!