解密

Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB

Total submit users: 2, Accepted users: 0

Problem 11552 : No special judgement

Problem description

password学中。有一种加密方法。叫做希尔加密法。

其加密过程例如以下: 

Step1:将待加密的字符串s={s[0], s[1], …… ,s[n-1]} (为简单起见。在本题中,字符串s仅仅含小写字母)按a->0, b->1,c->2, ……, y->24, z->25的规则转换为整形数组a={a[0], a[1], …… ,a[n-1]};

Step2: 将数组a分成长度相等的k个部分,每部分长度均为L(保证k*L=s待加密的字符串s的长度)

Setp3:将每部分左乘一L * L矩阵A,将结果向量中全部值对26取模后替换原来的部分。得到新的数组 

b={b[0], b[1], …… ,b[n-1]}, 

即b中的元素满足: 

(b[i * k],b[i * k + 1], ……, b[i * k + (L - 1)]) = (a[i * k],a[i * k + 1], ……, a[i * k + (L - 1)])*A

Step4:将数组b中的数按0->a, 1->b, 2->c, ……, 24->y, 25->z的规则转换为密文 

比如:加密july,矩阵A=[11 8;3 7](分号表示另起一行)

Step1:将july转化为数组a={9, 20, 11, 24};

Step2:将a分为{9, 20}。{11, 24}两部分 

Step3:因为[9, 20] * [11 8;3 7] = [159, 212]

[11, 24] * [11 8;3 7]=[193, 256]

故b=[159 % 26, 212 % 26, 193 % 26, 256 % 26] = [3, 4, 11, 22]

Step4:密文即为delw

你的任务是:给你密文和矩阵A。求原字符串

Input

第一行为一个整数T (0 < T < 20), 表示数据的组数.

每组数据的第一行为一个 仅仅有小写字母构成的 加密后 的字符串, 其长度不超过10000。

第二行为一个整数M(0 < M <= 100 且 字符串的长度能够整除M),表示矩阵A是M*M的矩阵 

后面M行。每行M个整数。 表示矩阵A,输入数据保证矩阵A主对角线上的元素与26互素

Output

对每组数据,输出一行,为密文所相应的原文

Sample Input

2

delw

2

11 8

3 7

pabqlzqii

3

1 14 2

5  9 2

4 7 3

Sample Output

july

qvtusjkcm

Problem Source

HUNNU Contest

希尔解密。须要先求逆矩阵。

我仅仅能过第一组。

。。

大神们,求解释。。。

  1. #include <math.h>
  2. #include <string.h>
  3. #include <malloc.h>
  4. #include <iostream>
  5. #include <iomanip>
  6. #include<stdio.h>
  7. using namespace std;
  8. #define N 105 //定义方阵的最大阶数为10
  9. //函数的声明部分
  10. double MatDet(double *p, int n); //求矩阵的行列式
  11. double Creat_M(double *p, int m, int n, int k); //求矩阵元素A(m, n)的代数余之式
  12. void print(double *p, int n); //输出矩阵n*n
  13. bool Gauss(double A[][N], double B[][N], int n); //採用部分主元的高斯消去法求方阵A的逆矩阵B
  14. double a[N][N],b[N][N];
  15. int c[N][N];
  16. double determ; //定义矩阵的行列式
  17. //int zimu[26];
  18. int gcd(int a,int b)
  19. {
  20. if(!b) return a;
  21. gcd(b,a%b);
  22. }
  23. void Print(int mm[],int k)
  24. {
  25. /*
  26. for(int i=0; i<k; i++)
  27. {
  28. printf("%d ",mm[i]);
  29. }
  30. printf("\n");*/
  31. for(int i=0; i<k; i++)
  32. {
  33. for(int j=0; j<k; j++)
  34. {
  35. printf("%d ",c[i][j]);
  36. }
  37. printf("\n");
  38. }
  39. // double tp[105]= {0};
  40. int tp[105]={0};
  41. for(int i=0; i<k; i++) //列
  42. {
  43. for(int j=0; j<k; j++) //行||mm的行
  44. {
  45. tp[i]+=mm[j]*c[j][i];
  46. // printf("tp=%d\tmm=%d\tb=%d\n",tp[i],mm[j],c[j][i]);
  47. }
  48. }
  49. for(int i=0; i<k; i++)
  50. {
  51. // int tmp=(int)(tp[i]);
  52. // printf("%d\t",tmp);
  53. printf("%c",((tp[i])%26+26)%26+'a');
  54. // while(tp[i]<0) tp[i]+=26;
  55. // printf("%c\n",(int)(tp[i])%26+'a');
  56. }
  57. // printf("\n");
  58. }
  59. int main()
  60. {
  61. // freopen("xier.txt","r",stdin);
  62. double *buffer, *p; //定义数组首地址指针变量
  63. int row, num; //定义矩阵的行数和矩阵元素个数
  64. // int i, j;
  65.  
  66. int n;
  67. // for(int i=0;i<26;i++)
  68. // zimu[i]=i;
  69. int T,len,M,mo[105];
  70. char mi[10005];
  71. scanf("%d",&T);
  72. while(T--)
  73. {
  74. scanf("%s",mi);
  75. len=strlen(mi);
  76. scanf("%d",&n);
  77. row=n;
  78. num = 2*row*row;
  79. buffer = (double *)calloc(num, sizeof(double)); //分配内存单元
  80. p = buffer;
  81. for(int i=0; i<n; i++)
  82. {
  83. for(int j=0; j<n; j++)
  84. {
  85. scanf("%lf",&a[i][j]);
  86. *p++=a[i][j];
  87. }
  88. }
  89. determ = MatDet(buffer, row); //求整个矩阵的行列式
  90. // printf("determ=%lf\n",determ);
  91. int d=gcd((int)(determ),27);
  92. d=(int)determ*27/d;
  93. // printf("***************************************d=%d\n",d);
  94. for (int i = 0; i < row; i++) //求逆矩阵
  95. {
  96. for (int j = 0; j < row; j++)
  97. {
  98. *(p+j*row+i) = Creat_M(buffer, i, j, row)*d/determ;
  99. }
  100. }
  101. print(p, row);
  102. free(buffer); //释放内存空间
  103. for(int i=0; i<len; i++)
  104. {
  105. // printf("mi=%c\n",mi[i]);
  106. mo[i%n]=mi[i]-'a';
  107. // printf("i=%d\tmo=%d\n",i%n,mo[i%n]);
  108. if((i+1)%n==0) Print(mo,n);
  109. }
  110. printf("\n");
  111.  
  112. // for(int i=0; i<n; i++)
  113. // {
  114. // for(int j=0; j<n; j++)
  115. // {
  116. // printf("%lf ",a[i][j]);
  117. // }
  118. // printf("\n");
  119. // }
  120. // if(Gauss(a,b,n))
  121. // {
  122. /*
  123. for (int i = 0; i < n; i++)
  124. {
  125. cout << setw(4);
  126. for (int j = 0; j < n; j++)
  127. {
  128. cout << b[i][j] << setw(10);
  129. }
  130. cout << endl;
  131. }*/
  132.  
  133. // }
  134. }
  135. return 0;
  136. }
  137. //-----------------------------------------------
  138. //功能: 求矩阵(n*n)的行列式
  139. //入口參数: 矩阵的首地址,矩阵的行数
  140. //返回值: 矩阵的行列式值
  141. //----------------------------------------------
  142. double MatDet(double *p, int n)
  143. {
  144. int r, c, m;
  145. int lop = 0;
  146. double result = 0;
  147. double mid = 1;
  148. if (n != 1)
  149. {
  150. lop = (n == 2) ? 1 : n; //控制求和循环次数,若为2阶,则循环1次。否则为n次
  151. for (m = 0; m < lop; m++)
  152. {
  153. mid = 1; //顺序求和, 主对角线元素相乘之和
  154. for (r = 0, c = m; r < n; r++, c++)
  155. {
  156. mid = mid * (*(p+r*n+c%n));
  157. }
  158. result += mid;
  159. }
  160. for (m = 0; m < lop; m++)
  161. {
  162. mid = 1; //逆序相减, 减去次对角线元素乘积
  163. for (r = 0, c = n-1-m+n; r < n; r++, c--)
  164. {
  165. mid = mid * (*(p+r*n+c%n));
  166. }
  167. result -= mid;
  168. }
  169. }
  170. else
  171. result = *p;
  172. return result;
  173. }
  174. //----------------------------------------------------------------------------
  175. //功能: 求k*k矩阵中元素A(m, n)的代数余之式
  176. //入口參数: k*k矩阵的首地址。矩阵元素A的下标m,n,矩阵行数k
  177. //返回值: k*k矩阵中元素A(m, n)的代数余之式
  178. //----------------------------------------------------------------------------
  179. double Creat_M(double *p, int m, int n, int k)
  180. {
  181. int len;
  182. int i, j;
  183. double mid_result = 0;
  184. int sign = 1;
  185. double *p_creat, *p_mid;
  186. len = (k-1)*(k-1); //k阶矩阵的代数余之式为k-1阶矩阵
  187. p_creat = (double*)calloc(len, sizeof(double)); //分配内存单元
  188. p_mid = p_creat;
  189. for (i = 0; i < k; i++)
  190. {
  191. for (j = 0; j < k; j++)
  192. {
  193. if (i != m && j != n) //将除第i行和第j列外的全部元素存储到以p_mid为首地址的内存单元
  194. {
  195. *p_mid++ = *(p+i*k+j);
  196. }
  197. }
  198. }
  199. sign = (m+n)%2 == 0 ?
  200.  
  201. 1 : -1; //代数余之式前面的正、负号
  202. mid_result = (double)sign*MatDet(p_creat, k-1);
  203. free(p_creat);
  204. return mid_result;
  205. }
  206. //-----------------------------------------------------
  207. //功能: 打印n*n矩阵
  208. //入口參数: n*n矩阵的首地址,矩阵的行数n
  209. //返回值: 无返回值
  210. //-----------------------------------------------------
  211. void print(double *p, int n)
  212. {
  213. int i, j;
  214. for (i = 0; i < n; i++)
  215. {
  216. // cout << setw(4);
  217. for (j = 0; j < n; j++)
  218. {
  219. c[i][j]=(int)*p++;
  220. while(c[i][j]<0) c[i][j]+=26;
  221. // cout << setiosflags(ios::right) << *p++ << setw(10);
  222. }
  223. // cout << endl;
  224. }
  225. }
  226. //------------------------------------------------------------------
  227. //功能: 採用部分主元的高斯消去法求方阵A的逆矩阵B
  228. //入口參数: 输入方阵,输出方阵,方阵阶数
  229. //返回值: true or false
  230. //-------------------------------------------------------------------
  231. bool Gauss(double A[][N], double B[][N], int n)
  232. {
  233. int i, j, k;
  234. double max, temp;
  235. double t[N][N]; //暂时矩阵
  236. //将A矩阵存放在暂时矩阵t[n][n]中
  237. for (i = 0; i < n; i++)
  238. {
  239. for (j = 0; j < n; j++)
  240. {
  241. t[i][j] = A[i][j];
  242. }
  243. }
  244. //初始化B矩阵为单位阵
  245. for (i = 0; i < n; i++)
  246. {
  247. for (j = 0; j < n; j++)
  248. {
  249. B[i][j] = (i == j) ? (double)1 : 0;
  250. }
  251. }
  252. for (i = 0; i < n; i++)
  253. {
  254. //寻找主元
  255. max = t[i][i];
  256. k = i;
  257. for (j = i+1; j < n; j++)
  258. {
  259. if (fabs(t[j][i]) > fabs(max))
  260. {
  261. max = t[j][i];
  262. k = j;
  263. }
  264. }
  265. //假设主元所在行不是第i行,进行行交换
  266. if (k != i)
  267. {
  268. for (j = 0; j < n; j++)
  269. {
  270. temp = t[i][j];
  271. t[i][j] = t[k][j];
  272. t[k][j] = temp;
  273. //B伴随交换
  274. temp = B[i][j];
  275. B[i][j] = B[k][j];
  276. B[k][j] = temp;
  277. }
  278. }
  279. //推断主元是否为0, 若是, 则矩阵A不是满秩矩阵,不存在逆矩阵
  280. if (t[i][i] == 0)
  281. {
  282. cout << "There is no inverse matrix!";
  283. return false;
  284. }
  285. //消去A的第i列除去i行以外的各行元素
  286. temp = t[i][i];
  287. for (j = 0; j < n; j++)
  288. {
  289. t[i][j] = t[i][j] / temp; //主对角线上的元素变为1
  290. B[i][j] = B[i][j] / temp; //伴随计算
  291. }
  292. for (j = 0; j < n; j++) //第0行->第n行
  293. {
  294. if (j != i) //不是第i行
  295. {
  296. temp = t[j][i];
  297. for (k = 0; k < n; k++) //第j行元素 - i行元素*j列i行元素
  298. {
  299. t[j][k] = t[j][k] - t[i][k]*temp;
  300. B[j][k] = B[j][k] - B[i][k]*temp;
  301. }
  302. }
  303. }
  304. }
  305. for(int i=0; i<n; i++)
  306. {
  307. for(int j=0; j<n; j++)
  308. {
  309. B[i][j]*=determ;
  310. }
  311. //printf("\n");
  312. }
  313. return true;
  314. }

希尔加密算法(湖南师范大学第六届大学生计算机程序设计竞赛)hnuoj11552的更多相关文章

  1. 湖南省第十三届大学生计算机程序设计竞赛 Football Training Camp 贪心

    2007: Football Training Camp[原创-转载请说明] Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 1 ...

  2. 浙江省第十六届大学生ACM程序设计竞赛部分题解

    E .Sequence in the Pocket sol:将数组copy一份,然后sort一下,找寻后面最多多少个元素在原数组中保持有序,用总个数减去已经有序的就是我们需要移动的次数. 思维题 #i ...

  3. CSUOJ1329——一行盒子_湖南省第九届大学生计算机程序设计竞赛

    题目是中文的我就不是说明了,比赛的时候看过题目后队友说是splay来做,细想来省赛不会出这么坑的题目吧. 于是比赛还有一个小时左右把该做的都做完了以后,我们队三个人都来思考这个题目了.不过还好很快我们 ...

  4. 2018湖南省第14届大学生计算机程序设计竞赛 D: 卖萌表情

    Description 已知以下 4 种都是卖萌表情(空白的部分可以是任意字符.竖线是便于展示的分隔符,没有实际意义): ^ ^ | ^ | < | > v | v v | > | ...

  5. 2018湖南省第14届大学生计算机程序设计竞赛 C: 时间旅行

    Description 假设 Bobo 位于时间轴(数轴)上 t0 点,他要使用时间机器回到区间 (0, h] 中. 当 Bobo 位于时间轴上 t 点,同时时间机器有 c 单位燃料时,他可以选择一个 ...

  6. 2018湖南省第14届大学生计算机程序设计竞赛 A字符画

    Description 读入 w,请输出 2018 的字符画,两个数字之间有 w 个空格.具体格式请参考样例输出. 1 ≤ w ≤ 2018 Input 输入文件只包含 1 个整数 w. Output ...

  7. 湖南省第九届大学生计算机程序设计竞赛 Interesting Calculator

    Interesting Calculator Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 163  Solved: 49 Description T ...

  8. csu 1503: 点弧之间的距离-湖南省第十届大学生计算机程序设计大赛

    这是--比量p并用交点连接中心不上弧.在于:它至p距离.是不是p与端点之间的最短距离 #include<iostream> #include<map> #include< ...

  9. 华东师范大学第十届ECNU Coder程序设计竞赛

    华东师范大学第十届ECNU Coder程序设计竞赛 浮点数模运算 solution 转成整数然后取模. 时间复杂度:\(O(1)\) 数螃蟹 solution 找出公差出现次数最多的作为公差,然后找出 ...

随机推荐

  1. Jsoup的简单的使用示例

    利用Jsoup中的相关方法实现网页中的数据爬去,本例子爬去的网页为比较流行的programmableweb中的mashup描述内容,然后为数据库中存在的mashup添加相应的描述. package c ...

  2. Solr.NET快速入门(四)【相似查询,拼写检查】

    相似查询 此功能会返回原始查询结果中返回的每个文档的类似文档列表. 参数通过QueryOptions的MoreLikeThis属性定义. 示例:搜索"apache",为结果中的每个 ...

  3. Kettle 版本及使用问题

    kettle 简介 Kettle也叫PDI (Pentaho Data Intergration) Kettle 版本及下载 7.1及更早版本: https://sourceforge.net/pro ...

  4. 使用IDEA搭建一个 Spring + Spring MVC 的Web项目(零配置文件)

    注解是Spring的一个构建的一个重要手段,减少写配置文件,下面解释一下一些要用到的注解: @Configuration 作用于类上面,声明当前类是一个配置类(相当于一个Spring的xml文件)@C ...

  5. javascript中对象属性搜索原则

    为什么通过对象就能访问到原型中的属性或者方法? 属性搜索原则: 1 首先会在对象本身查找有没有该属性,如果有直接返回 2 如果没有,此时就会在构造函数中查找通过this给对象添加的成员中有没有,如果有 ...

  6. 运行Tomcat闪退问题,报的错误:Unsupported major.minor version 51.0

    在MyEclipse中运行tomcat,tomcat闪退并且报以下错误. java.lang.UnsupportedClassVersionError: org/apache/catalina/sta ...

  7. Kotlin基础语法:变量、函数、类、枚举、控制流

    一切都需要从基础学起! 前言: 在Kotlin语言中,没有分号的概念了,也就是每一行代码,都不在需要用分号结束了 点击查看代码 定义 常量:val --相当于java当中的final 变量:var 关 ...

  8. 谈谈网页中的ajax

    一个页面上有很多的ajax请求,这样的页面右键查看源文件是没法看到全部的html.事实上,这种网页也是从正常的html页面改造过来的,常用的一个场景是,同一个区域大量循环,在动态页面里(比如jsp等) ...

  9. keyup.enter.native&click.native.prevent

    vue 监听键盘回车事件 @keyup.enter || @keyup.enter.native vue运行为v-on在监听键盘事件时,添加了特殊的键盘修饰符: <input v-on:keyu ...

  10. 记一次vip视频破解过程(爱奇艺 芒果 腾讯 优酷 )

    1. 在爱奇艺或者优酷中拿到视频的url地址.此时拿到的是加密地址(也可以直接在牛巴巴里面搜名字然后开f12跟踪路由) 2.进入牛巴巴vip视频解析网站.粘贴拿到的url.点击解析 3.f12在net ...