zoukankan      html  css  js  c++  java
  • sdut 2165:Crack Mathmen(第二届山东省省赛原题,数论)

    Crack Mathmen

    Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

    题目描述

     Since mathmen take security very seriously, they communicate in encrypted messages. They cipher their texts in this way: for every characther c in the message, they replace c with f(c) = (the ASCII code of c)n mod 1997 if f(c) < 10, they put two preceding zeros in front of f(c) to make it a three digit number; if 10 <= f(c) < 100, they put one preceding zero in front of f(c) to make it a three digit number.

    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?

    输入

     The input contains multiple test cases. The first line of the input contains a integer, indicating the number of test cases in the input. The first line of each test case contains a non-negative integer n (n <= 10^9). The second line of each test case contains a string of digits. The length of the string is at most 10^6.

    输出

     For each test case, output a line containing the plain text. If their are no or more than one possible plain text that can be encrypted as the input, then output "No Solution" (without quotation marks). Since mathmen use only alphebetical letters and digits, you can assume that no characters other than alphebetical letters and digits may occur in the plain text. Print a line between two test cases.

    示例输入

    3
    2
    590357035697030
    0
    001001001001001
    1000000000
    001001001001001

    示例输出

    World
    No Solution
    No Solution

    提示

     

    来源

     山东省第二届ACM大学生程序设计竞赛
     
      数论
      需要用到快速求幂二分法求幂),因为n <= 10^9,所以依次相乘求幂的方法会超时。
      另外可以用字母转换后的值为映射数组的下标,这样查找的时候,直接就可以找到该值对应的字母。
      快速求幂的地方多写了一个else,没注意到调试了2个小时,可见一个小小的粗心导致的错误能浪费多少宝贵的时间!特别是在比赛中,一定要注意细心!一味的求速度只会导致功亏一篑。
      参考两位小伙伴的博客:
      Vit     CYll
      代码:
     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <string.h>
     4 using namespace std;
     5 char a[1000001];
     6 char b[400001];
     7 char map[1000];    //映射
     8 int GetM(int t,int n)    //快速幂求模
     9 {
    10     int ans = 1;
    11     while(n){
    12         if(n & 1)
    13             ans = (ans*t)%997;
    14         t=t*t%997;
    15         n>>=1;
    16     }
    17     return ans;
    18 }
    19 bool GetMap(int n)    //产生映射表
    20 {
    21     int c;
    22     for(c=32;c<=126;c++){
    23         int t = GetM(c,n);
    24         if(map[t]!='')    //该值已有对应的字母
    25             return false;
    26         map[t] = char(c);
    27     }
    28     return true;
    29 }
    30 int main()
    31 {
    32     int T;
    33     scanf("%d",&T);
    34     while(T--){
    35         int i,n,len = 0;
    36         scanf("%d",&n);
    37         scanf("%s",a);
    38         memset(map,'',sizeof(map));    //初始化映射
    39         if(!GetMap(n)){    //产生映射.如果失败,输出提示,退出本次循环
    40             printf("No Solution
    ");
    41             continue;
    42         }
    43         //没有冲突,产生映射成功,根据映射表解码
    44         int t = 0;
    45         int Len = strlen(a);
    46         for(i=0;i<Len;i+=3){
    47             t = (a[i]-'0')*100 + (a[i+1]-'0')*10 + (a[i+2]-'0');
    48             if(map[t]=='')    //没有对应的映射
    49                 break;
    50             b[len++] = map[t];
    51         }
    52         if(i<Len)    //提前跳出
    53             printf("No Solution
    ");
    54         else{
    55             b[len] = '';
    56             cout<<b<<endl;
    57         }
    58     }
    59     return 0;
    60 }  

    Freecode : www.cnblogs.com/yym2013

  • 相关阅读:
    Web服务器—Nginx
    Web服务器—IIS
    Linux—主机扫描工具(Nmap)
    Linux—系统关机命令详解
    Linux—开机启动过程详解
    Python—版本和环境的管理工具(Pipenv)
    Flask—好的博客
    Mysql—事务原理与详解
    汇编刷题:统计内存中的一个十六位二进制数 位值为1的位个数之和
    汇编刷题:在M单元和N单元分别存有一个8位无符号数36H和95H,要求比较并输出 M大于N 或者 M小于N
  • 原文地址:https://www.cnblogs.com/yym2013/p/3685466.html
Copyright © 2011-2022 走看看