题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1009

题目大意:给你三个转换轮,只有当第一个转换轮转动一圈后第二个才会转,当第二个转动一圈后第三个才会转。转换轮的意思是我按动一个按钮,显示器经过转换轮的转换显示另外一个字母。每按下一个按钮,第一个转换轮都会转动一次。

叉姐说得好,多学习一下思维方法,有些问题都是能够很高效率的想出来的。脑洞什么的全是骗人的。

注意看这张图:

中间转动轮的点, 左右两边是一一对应的。

也就是说,无论转动轮怎么转,都能把左边的keyboard和右边的display一一对应上,不重不漏。

那么,我们给rotor左边的接口依次标号1,2,3,4,5,6 并且根据第一个状态读出对应关系。即1,-1,1,2,0,-3

经过对应关系,我们把keyboard上的标为A集合{a,b,c,d,e,f} 经过对应关系B {1,-1,1,2,0,-3}, 得到 {a+1,b-1,c+1,d+2,e+0,f-3} => {b,a,d,f,e,c}

然后再经过一层对应关系C {0,0,1,1,1,-3} => {b,a,e,f,c,d} ,注意第二个关系是把a+0,b+0,c+1,d+1,f+1,e-3,也就是说不管上一个映射怎么变,这一个还是对abcdef进行映射。

那么,这就可以列出来转移映射关系式了: cc[i] = tmp[i]+r[tmp[i]];

再加上偏移:cc[i] = tmp[i]+r[((tmp[i]-st)%m+m)%m]

再对整个做负数处理:cc[i] = ((tmp[i]+r[((tmp[i]-st)%m+m)%m])%m+m)%m

我就是这里没想好,卡了好久。

到这里,题目就做了一大半。

接下来,我们发现A经过三次映射到了D

那么也就是说我们可以把中间的关系合并起来  A -> D。

表示成f(A) = D

那么求反函数即可g(D) = A

接下来就是链表的事情咯。

 #include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <vector>
#include <map>
#include <set>
#include <iterator>
#include <functional>
#include <cmath>
#include <numeric>
#include <ctime>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define PB push_back
#define MP make_pair
#define SZ size()
#define CL clear()
#define AA first
#define BB second
#define EPS 1e-8
#define ZERO(x) memset((x),0,sizeof(x))
const int INF = ~0U>>;
const double PI = acos(-1.0); int m,n;
char r[][];
int e[][];
const int MAX_N = **;
int tmp[]; struct CircularNode{
int lst[];
int num;
CircularNode *next;
CircularNode(int n){
memset(lst,,sizeof(lst));
num = n;
next = NULL;
}
~CircularNode(){
if( next ){
delete next;
next = NULL;
}
}
}; struct CircularList{
CircularNode *rt,*cur;
~CircularList(){
delete rt;
}
CircularList(){
rt = NULL;
}
void push_back(int a[],int m){
if( !rt ) {
rt = new CircularNode(m);
cur = rt;
} else {
cur->next = new CircularNode(m);
cur = cur->next;
} for(int j=;j<m;j++){
cur->lst[a[j]] = j;
}
}
}; void mapping(int *r,int st){
int cc[];
for(int i=;i<m;i++){
cc[i] = ((tmp[i]+r[(tmp[i]-st+m)%m])%m+m)%m;
}
for(int i=;i<m;i++){
tmp[i] = cc[i];
}
} int main(){
int kase = ;
while(scanf("%d",&m),m){
if(kase!=) puts("");
printf("Enigma %d:\n",kase++);
for(int i=;i<;i++) scanf("%s",r[i]);
for(int i=;i<;i++){
for(int j=;j<m;j++){
e[i][j] = r[i][j] - 'A' - j;
// printf("%d ",e[i][j]);
}
// puts("");
} CircularList *aCircularList = new CircularList; for(int st1=;st1<m;st1++){
for(int st2=;st2<m;st2++){
for(int st3=;st3<m;st3++){
for(int i=;i<m;i++) tmp[i] = i;
mapping(e[],st3);
// for(int i=0;i<m;i++) printf("%d ",tmp[i]); puts("");
mapping(e[],st2);
// for(int i=0;i<m;i++) printf("%d ",tmp[i]); puts("");
mapping(e[],st1);
// for(int i=0;i<m;i++) printf("%d ",tmp[i]); puts("");
aCircularList->push_back(tmp,m);
// for(int i=0;i<m;i++){
// printf("%d ",aCircularList->cur->lst[i]);
// }
// puts("");
}
// exit(0);
}
} scanf("%d",&n);
getchar();
int kase = ;
while(n--){
CircularNode *p = aCircularList->rt;
char c;
while( (c=getchar())!='\n' ){
// printf("%d\n",p->lst[c-'A']);
putchar('a'+p->lst[c-'A']);
p = p->next;
if(!p) p = aCircularList->rt;
}
puts("");
} delete aCircularList;
}
return ;
} /*
6
FDBCAE
ABDEFC
CDAFEB
1
ACE
*/

[ZOJ 1009] Enigma (模拟)的更多相关文章

  1. 1009 Enigma

    本题的重点是理解清楚题意并能代码模拟.形式是二战德国密码机,和数据结构.算法联系较少. #include <stdio.h> #include <string.h> int m ...

  2. Enigma模拟-Python

    设计思想 Enigma机的机械结构: 键盘:加密人员通过键盘进行输入 转子:Enigma机上一般装有至少3个转轮.每个转轮有代表26个字母的触头和触点,触点和触头在转轮内部有导线相连(一个转轮相当于一 ...

  3. A - Jugs ZOJ - 1005 (模拟)

    题目链接:https://cn.vjudge.net/contest/281037#problem/A 题目大意:给你a,b,n.a代表第一个杯子的容量,b代表第二个杯子的容量,然后一共有6种操作.让 ...

  4. ZOJ 2610 Puzzle 模拟

    大模拟:枚举6个方向.检查每一个0是否能移动 Puzzle Time Limit: 2 Seconds      Memory Limit: 65536 KB Little Georgie likes ...

  5. Capture the Flag ZOJ - 3879(模拟题)

    In computer security, Capture the Flag (CTF) is a computer security competition. CTF contests are us ...

  6. ZOJ 3705 Applications 模拟

    #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include< ...

  7. ZOJ 3652 Maze 模拟,bfs,读题 难度:2

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4842 要注意题目中两点: 1.在踏入妖怪控制的区域那一刹那,先减行动力,然后才 ...

  8. ZOJ 1122 Clock(模拟)

    Clock Time Limit: 2 Seconds      Memory Limit: 65536 KB You are given a standard 12-hour clock with ...

  9. POJ题目细究

    acm之pku题目分类 对ACM有兴趣的同学们可以看看 DP:  1011   NTA                 简单题  1013   Great Equipment     简单题  102 ...

随机推荐

  1. 使用bind(this)的情况

    1.setInterval().setTimeout()的回调函数,一定要加.bind(this)方法. 原因是:在setInterval()中定义的回调函数,是在同步代码执行完后,随着事件触发来异步 ...

  2. maven项目依赖小试牛刀

    1.先建立空的wbh-parent,留下pom.xml;将项目中用的jar包依赖全放进去: 2.建立core项目,当然全是maven的,这个建好后,是用来让其他项目引用的,所以必须用maven ins ...

  3. Settings.System.getInt获取Setting里的设置信息

    数据库的路径:/data/data/com.android.providers.settings. 获取飞行模式: Settings.System.getInt(mContext.getContent ...

  4. C#分析搜索引擎URL得到搜索关键字,并判断页面停留时间以及来源页面

    前台代码: var start; var end; var state; var lasturl = document.referrer; start = new Date($.ajax({ asyn ...

  5. JQ查找替换

    resultStr = resultStr.replace(/\n/gi , "<br />"); //可以全部替换resultStr = resultStr.repl ...

  6. linux常用方法

    同步时间 ntpdate us.pool.ntp.org 查看http的并发请求数及其TCP连接状态 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in ...

  7. erlang和go之间桥接库相关

    https://github.com/goerlang

  8. class对象不太明白(待解答)

    如下:定义了一个Servletcontext的Listener,希望获取当前WEB应用的某一个文件对应的输入流 不懂为什么要这样获取?不是可以直接用servletContext.getResource ...

  9. 在Linux中使用VS Code编译调试C++项目

    最近项目需求,需要在Linux下开发C++相关项目,经过一番摸索,简单总结了一下如何通过VS Code进行编译调试的一些注意事项. 关于VS Code在Linux下的安装这里就不提了,不管是CentO ...

  10. (三)java的数据类型

    java是一种强类型的语言,所谓强类型,意味着每个变量都要有确定的类型,每个表达式也要有明确的类型,包括传递的某些参数.java中从大的方面分有两大数据类型,分别是基本数据类型和引用数据类型,基本数据 ...