Crack Mathmen
题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2165
Time Limit: 1000ms Memory limit: 65536K
题目描述No Solution
这道题,当时比赛时,昊G在翻译完大部分题目后拉着晨阳G俩孩子默默做了N久也没A出来,后来再讲这道题的时候懊悔不已。。。他们一直用数论的密码学,用RSA加密算法来解决,然后题意也没读太透,以为只有字母。之前应该能A出来的,但是没有加数字,结果。。。
言归正传,昊G说,RSA加密算法分两种,一种是可以写出解密方程的,另一种可能没有解密方程,就用打表来解决。于是乎,他们研究后发现找不出解密方程,所以打表解决。(但是,前文说了,他们没打数字的表,所以WA)。这道题,就是用打表解决。
题意就是 给你一个加过密的字符串,让你解密。
加密的过程是 一个字符比如b,b的ASCII码为98, 98^n%997
如果n为2,98^2%997=631.
所以 所给的加密串中若出现 631 则可翻译为b。
加密串为3的倍数,每三个数代表一个字符。(不足三位数用0补足,因为最后%997所以不会有大于3位数情况)
最终由两种 No Solution
① 前文b对应631,若出现另一个字母也对应631,则有二义性,所以No Solution
②加密串中取出了一组数,假设555,但是555没有对应任何一个字母或者数字,则No Solution
解题步骤:
①收取输入的n和加密串(最多至100万个)
②根据n,做一个字典,讲所有字母和数字都存储于数组中。
(此处,做 x(代表字符ASCII值)^n%997,由两种方法,第一种是吉大的模板(用的二进制方法),还有一种直接int型的。)
③然后翻译加密串。
在第②和③要随时注意 No Solution情况。
#include <iostream> #include <string.h> #include <string> using namespace std; char tran[1000]; char key[1000001]; char ans[340000]; bool flag; // 大数取模的二进制方法 // a^b0 mod n int mod_exp(int a,int b0,int n) { if( a>n ) a%=n; int i,d=1,b[35]; for( i=0;i<35;++i ) { b[i]=b0%2; b0 /= 2; if( b0==0 ) break; }//b[i]b[i-1]...b[0] 为b0的二进制表示 for( ;i>=0;--i ) { d= (d*d)%n; if( b[i]==1 ) d=(d*a)%n; } return d; } /* int mod_exp(int a,int b,int n) { int ans=1; while(b) { if(b&1) ans = (ans * a) % n; a = a * a % n; b = b >> 1; } return ans; } */ // 构造字典 void judge_c(int n) { int i,temp; for(i=48; i<58; ++i) { temp=mod_exp(i,n,997); if( tran[temp]!=-1 ) return; else tran[temp]=char(i); } for(i=65; i<91; ++i) { temp=mod_exp(i,n,997); if( tran[temp]!=-1 ) return; else tran[temp]=char(i); } for(i=97; i<123; ++i) { temp=mod_exp(i,n,997); if( tran[temp]!=-1 ) return; else tran[temp]=char(i); } flag=1; return; } // 进行翻译 void find_ans(int len) { int i,sum,js=0; for(i=0; i<len; i+=3) { sum=(key[i]-'0')*100+(key[i+1]-'0')*10+key[i+2]-'0'; if( tran[sum]==-1 ) { cout<<"No Solution"<<endl; return; } ans[js++]=tran[sum]; } for(i=0; i<js; ++i) cout<<ans[i]; cout<<endl; } int main() { int test,n; cin>>test; while(test--) { memset(tran,-1,sizeof(tran)); cin>>n; // 取回车 cin.getline(key,1000000,'\n'); cin.getline(key,1000000,'\n'); flag=0; judge_c(n); if(!flag) { cout<<"No Solution"<<endl; continue; } else find_ans(strlen(key)); } return 0; }