传送门:SDUT 2165
题目大意:
对于每一个英文字符和数字,我们按照以下加密原则加密:(字符的ASCII码值)^n mod 997 = y,得到三位数的 y(如果不满三位则补0)。
现在给你 n 和 y 的值,让你求加密之前的明文是什么。如果明文不存在或者不唯一则输出 No Solution。
思路:
如果给定 n、y,让求 x^n mod 997 = y,中的 x 的值是很难求的。所以我们可以换个角度思考。
y值的来源只可能是大小写字母和数字字符加密后得到的,并且应该一一对应,而这些字符的个数有限,所以我们可以先通过快速幂得到每个字符对应的密文值。然后对于截获的密文中的每一个值去找它对应的字符,如果不存在或者存在多个则无解。
因为要按照密文值找加密前的字符,所以我用的 vector数组存储的每个密文值对应的密文可能是什么。
代码:
#include<stdio.h> #include<string.h> #include<iostream> #include<vector> using namespace std; char s[1000010],ans[400010]; int q_mod(int a,int b,int m) { //快速幂取模 int base=a,r=1; while(b) { if(b&1) r=(r*base)%m; base=(base*base)%m; b>>=1; } return r; } int main() { int i,t,n,a,f,rlt,len,tol; vector<char> vct[1000]; //记录每个密文值对应的密文 scanf("%d",&t); while(t--) { scanf("%d%s",&n,s); for(i=0;i<1000;i++) vct[i].clear(); for(i='a';i<='z';i++) { //计算 a~z 对应的密文值 rlt=q_mod(i,n,997); vct[rlt].push_back((char)i); } for(i='A';i<='Z';i++) { //计算 A~Z 对应的密文值 rlt=q_mod(i,n,997); vct[rlt].push_back((char)i); } for(i='0';i<='9';i++) { //计算 0~9 对应的密文值 rlt=q_mod(i,n,997); vct[rlt].push_back((char)i); } f=1; tol=0; len=strlen(s); for(i=0;i<len;i+=3) { a=(s[i]-'0')*100+(s[i+1]-'0')*10+(s[i+2]-'0'); if(vct[a].size()>1||vct[a].size()==0) { //如果密文不存在或存在多个 f=0; break; } else ans[tol++]=vct[a][0]; //记录结果 } if(!f) printf("No Solution\n"); else { for(i=0;i<tol;i++) printf("%c",ans[i]); printf("\n"); } } return 0; }