1 条题解
-
0
问题理解
我们需要从给定的密文 和密钥 中恢复明文 。加密过程如下:
-
计算 : [ d = \left\lfloor n^{1.5} + x \right\rfloor \mod n ] 其中 是明文或密文的长度。
-
加密 :
- 是 中位置与 在 中的位置相同的符号。
- 即,找到 在 中的位置 ,然后 。
-
加密其他 :
- 对于 , 是 中位置等于 在 中的位置与 在 中的位置的异或。
- 即,$pos_C[j] = pos_P[M[j]] \oplus pos_S[M[(j+1) \mod n]]$,然后 。
解密思路分析
解密的目标是逆向上述过程:
-
计算 :
- 同样使用 。
-
解密 :
- ,因此 。
- 因为 是 的排列,可以找到 。
-
解密其他 :
- 对于 ,$pos_C[j] = pos_P[M[j]] \oplus pos_S[M[(j+1) \mod n]]$。
- 这是一个方程,我们需要解出 和 。
- 由于 是 在 中的位置,我们可以利用后续的 值来推断 。
解密算法实现
从 开始,逆向填充 :
-
初始化:
- 读取 , , , 。
- 计算 和 。
-
解密 :
- 找到 在 中的位置 ,然后 。
-
解密其他 :
- 从 开始,逆向遍历到 。
- 对于每个 ,计算 在 中的位置 。
- 计算 在 中的位置 。
- 然后 。
代码实现
#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> int main() { int x,i,j; while(~scanf("%d",&x)) { char s[35],p[35],c[70],m[70]; int splen,n,d; if(x==0) break; scanf("%s\n%s\n%s",s,p,c); splen=strlen(s); n=strlen(c); d=((int)(pow(n,1.5))+x)%n; for(i=0;i<splen;i++) if(c[d]==s[i]) m[d]=p[i]; int temp1,temp2;//分别记录c[i]在s中的位置,与m[(i+1)%n]在s中的位置 for(i=d-1;(i+n)%n!=d;i--) { if(i<0) i=(i+n)%n; for(j=0;j<splen;j++) if(c[i]==s[j]) { temp1=j; break; } for(j=0;j<splen;j++) if(m[(i+1)%n]==s[j]) { temp2=j; break; } m[i]=p[temp1^temp2];//运用题解中提到的公式 } for(j=0;j<n;j++) printf("%c",m[j]); printf("\n"); } return 0; }
代码解释
-
输入读取:
- 读取 , , , 。
-
计算 :
- 使用 。
-
解密 :
- 找到 在 中的位置,然后 。
-
解密其他位置:
- 对于每个 :
- 找到 在 中的位置 。
- 找到 在 中的位置 pos_M_next。
- 计算 pos_P_M_i = pos_C \oplus pos_M_next。
- M[i] = P[pos_P_M_i]。
- 对于每个 :
-
输出结果:
- 打印解密后的 。
-
- 1
信息
- ID
- 1016
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者