题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2165
For example, if they choose n = 2 and the message is "World" (without quotation marks), they encode the message like this:
1. the first character is ‘W‘, and it‘s ASCII code is 87. Then f(′W′) = 87^2 mod 997 = 590.
2. the second character is ‘o‘, and it‘s ASCII code is 111. Then f(′o′) = 111^2 mod 997 = 357.
3. the third character is ‘r‘, and it‘s ASCII code is 114. Then f(′r′) = 114^2 mod 997 = 35. Since 10 <= f(′r′) < 100, they add a 0 in front and make it 035.
4. the forth character is ‘l‘, and it‘s ASCII code is 108. Then f(′l′) = 108^2 mod 997 = 697.
5. the fifth character is ‘d‘, and it‘s ASCII code is 100. Then f(′d′) = 100^2 mod 997 = 30. Since 10 <= f(′d′) < 100, they add a 0 in front and make it 030.
6. Hence, the encrypted message is "590357035697030".
One day, an encrypted message a mathman sent was intercepted by the human being. As the cleverest one, could you find out what the plain text (i.e., the message before encryption) was?
3 2 590357035697030 0 001001001001001 1000000000 001001001001001
World No Solution No Solution 第一行3,代表三组数据,然后每组输入两行 第一行是 n 第二行是要破译的密码; 把密码分成每三个数字一组,去破译 例如第一组样例 590357035697030 把它每3个拆成一组,每组翻译成一个字符,第一行输入的 n=2,代表该字符asc码的几次方 例如 590 = 87^2%997 , ‘W的‘asc码就是 87,, 所以第一个字母是 W,依次类推输出了 World; 可以看出只要我们知道了asc码,我们就能求出 对应的字符,很容易想到打表,因为题目说翻译后的密码只包含大小写字母和数字,数组不用开很大就能储存; 而 对于求幂取模,,直接套用快速幂模板就行了。 No Solution的情况: 1:没有对应的字符 2:对应的字符多于一个#include <stdio.h> #include <cmath> #include <cstring> #include <stdlib.h> typedef long long ll; const int maxn=1000000+10; char str[maxn]; char test[maxn/3][5]; char ar[1010]; int signaa; ll pow_mod(ll x,ll n, ll mod) //快速幂模板 { ll res=1; x=x%mod; while(n>0) { if(n%2) { res=res*x%mod; } x=x*x%mod; n/=2; } return res; } int main() { int n; scanf("%d",&n); int cas=0; while(n--) { signaa=0; memset(ar,'\0',sizeof(ar)); memset(str,'\0',sizeof(str)); int t; scanf("%d",&t); getchar(); int i;int res; for(int i=48;i<=122;i++) { if((i>=48&&i<=57)||(i>=65&&i<=90)||(i>=97&&i<=122)) { res=pow_mod(i,t,997);//输入了t之后,把求出的值储存到字符数组ar的坐标,把该位置的asc码转换成字符存到ac中 if(ar[res]=='\0') //用来标记是否有重复的密码 ar[res]=char(i);//把该位置的asc码转换成字符存到ac中 else { signaa=1;//如果重复,标记变量变为1; break; } } } gets(str); int len=strlen(str); int k=0,s=0; for(int i=0;i<len;i++) { if(i%3==0) { k++; s=0; } test[k][s++]=str[i]; //每三个字符存到另一个数组中,,当然也可以int res=(str[i]-'0')*100+(str[i+1]-'0')*10+str[i+2]-'0';更简单 } if(signaa) { printf("No Solution\n"); continue; } else { for(int i=1;i<=k;i++) { int res=atoi(test[i]); if(ar[res]!='\0') printf("%c",ar[res]); else { signaa=1; break; } } if(signaa) { printf("No Solution\n"); } else printf("\n"); } } return 0; }
第二届山东省ACM省赛回顾 Crack Mathmen(打表)
原文地址:http://blog.csdn.net/chaiwenjun000/article/details/45418139