Crack Mathmen
Problem Description
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?
Input
Output
Example Input
3 2 590357035697030 0 001001001001001 1000000000 001001001001001
Example Output
World No Solution No Solution
分析:题意是,对字母和数字进行编码,每个字母或数字的编码都是三位,编码规则为该字符的ASCII值的n次方mod 997。并保证对每个字符(只包括字母和数字)的编码存在且唯一,若译码结果不是字符或数字则输出No Solution
用快速幂求出相应的编码,再用编码做为数字下表存字符,例如ch[ 590 ]='W';
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <string> #include <stack> using namespace std; typedef long long ll; #define PI 3.1415926535897932 #define E 2.718281828459045 #define INF 0xffffffff//0x3f3f3f3f #define mod 997 const int M=1005; int n,m; int cnt; int sx,sy,sz; int mp[1000][1000]; int pa[M*10],rankk[M]; int head[M*6],vis[M*100]; int dis[M*100]; ll prime[M*1000]; bool isprime[M*1000]; int lowcost[M],closet[M]; char st1[5050],st2[5050]; int len[M*6]; typedef pair<int ,int> ac; //vector<int> g[M*10]; ll dp[1000][2000]; int has[10500]; int month[13]= {0,31,59,90,120,151,181,212,243,273,304,334,0}; int dir[8][2]= {{0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1}}; void getpri() { ll i; int j; cnt=0; memset(isprime,false,sizeof(isprime)); for(i=2; i<1000000LL; i++) { if(!isprime[i])prime[cnt++]=i; for(j=0; j<cnt&&prime[j]*i<1000000LL; j++) { isprime[i*prime[j]]=1; if(i%prime[j]==0)break; } } } struct node { int v,w; node(int vv,int ww) { v=vv; w=ww; } }; vector<int> g[M*100]; char str[10000005]; int bit[50]; char str01[1000005],strr[1000005]; int qmod(int x,int b) { int ans=1; while(b) { if(b&1) ans=(ans*x)%mod; x=(x*x)%mod; b>>=1; } return ans%mod; } bool init(){ //打表 int p; memset(str01,'\0',sizeof(str01)); for(int i=32;i<=126;i++){//键盘上存在字符的asc码表 p=qmod(i,n); if(str01[p]=='\0')//判断 原码 ->加密码 转换过程中是否重复,重复则直接返回false str01[p]=char(i);// 加密码 作数组下标,匹配时直接寻找,无需查找 else return false;//保证对每个字符(只包括字母和数字)的编码存在且唯一 } return true; } ll sum[5000],a[5000]; int main() { int i,j,k,t; bool flag; scanf("%d",&t); while(t--) { flag=true; memset(strr,0,sizeof(strr)); j=0; scanf("%d",&n); //if(n==0) scanf("%s",str); if(n==0){printf("No Solution\n");continue;} int len=strlen(str); if(init()){ for(i=0;i<len;i+=3){//每三个确定一个字符 int tmp=(str[i]-'0')*100+(str[i+1]-'0')*10+(str[i+2]-'0'); if(str01[tmp]=='\0'){//不存在字符源码 flag=false; break; } strr[j++]=str01[tmp];//把翻译过来的存一下 好输出 } } else flag=false; if(flag)printf("%s\n",strr);//要么就for循环输出,上边就不用memset了,否则WA出血。。。 else printf("No Solution\n"); } return 0; }