HSCTF-2017-众所周知系列
不起眼幼蛇培育法
题目
众所周知,大蛇丸是忍界首席科学家,然而一直没有女朋友。
有一天,他在斜坡看到一条幼蛇,一见钟情了。
不过他不知道这条幼蛇长大之后会不会变成母猪,有点方。
你可以帮帮他吗?
附件
答案
HSCTF{Megumi-or-Sow?}
做法
法1:玩通关,蛇长大即可(注意蛇要反向控制)
法2:用IDA打开程序,可以找到flag的ASCII码异或后组成的数组,异或回去即可
(后来发现我忘记注释掉未经异或的flag(第23行),其实直接用文本编辑器打开exe搜“HSCTF”就搜得出来)
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
/************************************************************************ > File Name: gluttonous_snake.cpp > Author: gou4shi1 > Mail: admin@goushi.me > Created Time: 2016年05月17日 星期二 20时19分21秒 ************************************************************************/ #include <iostream> //cin cout #include <cstdlib> //srand();rand();system(); #include <ctime> //time(); #include <conio.h> //kbhit();getch(); #include <windows.h> //Sleep();SetWindow()、SetCursorPosition()、SetTextColorToXXX()内调用的函数 #include <cstdio> using namespace std; //把方向按顺时针顺序映射成数字 #define LEFT 0 #define UP 1 #define RIGHT 2 #define DOWN 3 const char flag[] = "HSCTF{Megumi-or-Sow?}"; const int fff[] = {72, 82, 65, 87, 66, 126, 75, 98, 111, 124, 103, 98, 33, 98, 124, 34, 67, 126, 101, 44, 105}; const int fff_len = 21; //速度相关常量(每走一步后的等待时间越短,蛇走得越快): //t0:初始间隔时间;k:蛇身长度对速度的影响因子;min,max:控制间隔时间范围 const int sleep_time_t0 = 200,sleep_time_k = 25,sleep_time_min = 75,sleep_time_max = 250; //蛇可走的空间的范围、初始长度 const int snake_map_min = 1,snake_map_max = 18,snake_initila_len = 5; //向各方向走的坐标偏移量 const int dx[] = {-1,0,1,0}; const int dy[] = {0,-1,0,1}; //返回一个在[l,r]间的随机数 int random(int l,int r) { return l + rand() % (r - l + 1); //采用对区间大小求余的方法 } //设置窗口属性 void SetWindow() { SetConsoleTitle("Saenai Heroine no Sodatekata"); //设置窗口标题 COORD size = {50,30}; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),size); //设置窗口缓存区大小 SMALL_RECT rect = {1,1,50,30}; SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE),true,&rect); //设置窗口大小 } //设置光标位置 void SetCursorPosition(int x,int y) { COORD coord = {x,y}; //warning: narrowing conversion of 'x' from 'int' to 'SHORT {aka short int}' SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord); } //设置文本颜色为白色 void SetTextColorToWhite() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); } //设置文本颜色为红色 void SetTextColorToRed() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_INTENSITY); } //设置文本颜色为绿色 void SetTextColorToGreen() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY); } //设置文本颜色为蓝色 void SetTextColorToBlue() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE|FOREGROUND_INTENSITY); } //设置文本颜色为黄色 void SetTextColorToYello() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY); } //在(x*2+1,y)处输出字符ch //x*2+1是为了美观整齐,故内在坐标与屏幕坐标存在这一映射关系 //控制台坐标系:原点为左上角;x轴正方向为向右;y轴正方向为向下; void print(int x,int y,char ch) { SetCursorPosition(x * 2 + 1,y); cout << ch; } //屏幕内容初始化 void ScreenInit() { system("cls"); //调用控制台命令清除屏幕内容 SetTextColorToWhite(); for (int i = snake_map_min - 1; i <= snake_map_max + 1; ++i) for (int j = snake_map_min - 1; j <= snake_map_max + 1; ++j) if (i < snake_map_min || i > snake_map_max || j < snake_map_min || j > snake_map_max) print(i,j,'#'); //输出白色的围墙 } //蛇的结点,蛇采用链表实现 struct SNAKE_NODE { SNAKE_NODE(int X = 0,int Y = 0,SNAKE_NODE *SUC = NULL,SNAKE_NODE *PRE = NULL) : x(X),y(Y),suc(SUC),pre(PRE) {} int x,y; //坐标 SNAKE_NODE *suc,*pre; //前驱与后继 }; //蛇 class SNAKE { public: SNAKE(); //初始化蛇 void GenerateFood(); //生成食物 void ChangeDir(char); //改变方向 bool move(); //移动一步 bool exist(int x,int y) { return snake_map[x][y]; } //返回(x,y)处是否存在蛇 int GetLen() { return len; } //返回蛇身长度 private: void AddHead(int x,int y); //在蛇头前方(x,y)处插入结点 void DelTail(); //删除蛇尾结点 void PrintSnake(); SNAKE_NODE *head,*tail; //分别指向蛇头与蛇尾 int dir,len,food_x,food_y; //前进方向,蛇身长度,食物坐标 bool snake_map[snake_map_max + 1][snake_map_max + 1]; //蛇身地图:true表示那一点有蛇 }; SNAKE::SNAKE() { food_x = food_y = 0; tail = head = NULL; for (int i = snake_map_min; i <= snake_map_max; ++i) for (int j = snake_map_min; j <= snake_map_max; ++j) snake_map[i][j] = false; len = 0; dir = random(0,3); int snake_initial_x = random(snake_map_min+snake_initila_len,snake_map_max-snake_initila_len); int snake_initial_y = random(snake_map_min+snake_initila_len,snake_map_max-snake_initila_len); //随机初始化蛇 for (int i = 0; i != snake_initila_len; ++i) AddHead(snake_initial_x + dx[dir] * i,snake_initial_y + dy[dir] * i); PrintSnake(); } void SNAKE::GenerateFood() { food_x = random(snake_map_min,snake_map_max); food_y = random(snake_map_min,snake_map_max); if (exist(food_x,food_y)) { GenerateFood(); //若随机出来的点有蛇,则再随机一蛇身次,此方案可保证蛇外各点生成食物的概率一样 return; } SetTextColorToRed(); print(food_x,food_y,'@'); //在食物处输出红色的'@'标志 SetCursorPosition(head->x * 2 + 1,head->y); //把光标位置设置为蛇头 } void SNAKE::ChangeDir(char x) { switch (x) //若x不是wasd之一,则方向不变 { case 'd' : case 'D' : if (dir != RIGHT) //当前方向为向左时,不能一下子变成向右,下同 dir = LEFT; break; case 's' : case 'S' : if (dir != DOWN) dir = UP; break; case 'a' : case 'A' : if (dir != LEFT) dir = RIGHT; break; case 'w' : case 'W' : if (dir != UP) dir = DOWN; break; } } bool SNAKE::move() { int x_new = head->x + dx[dir]; int y_new = head->y + dy[dir]; if (x_new < snake_map_min || x_new > snake_map_max) return false; if (y_new < snake_map_min || y_new > snake_map_max) return false; //若撞墙则返回false,游戏结束 if (exist(x_new,y_new)) //若撞蛇则返回false,游戏结束 if (!(x_new == tail->x && y_new == tail->y)) //但可以“撞”蛇尾,因为实际上蛇头与蛇尾是同时移动的,实际上并不会撞上去 return false; AddHead(x_new,y_new); //在蛇头前方插入新结点,即向前走一步 if (x_new == food_x && y_new == food_y) GenerateFood(); //若吃到了食物,则不用删除蛇尾,即蛇身变长一格,且需生成新的食物 else DelTail(); //若没吃到食物,则需删除蛇尾,以达到蛇向前走一步而蛇身长度不变的效果 while (len > fff_len) DelTail(); PrintSnake(); return true; } void SNAKE::AddHead(int x,int y) { SNAKE_NODE *node_new = new SNAKE_NODE(x,y,NULL,head); //新结点的suc为NULL,pre为旧蛇头 if (head == NULL) tail = node_new; //若旧蛇头为NULL,即向空蛇插入新结点,需把蛇尾指向新结点 else head->suc = node_new; //把旧蛇头的suc指向新结点 head = node_new; //蛇头指向新结点 snake_map[head->x][head->y] = true; //更新蛇身地图 ++len; //更新蛇身长度 } void SNAKE::DelTail() { SNAKE_NODE *p = tail; //p指向旧蛇尾 print(p->x,p->y,' '); //在旧蛇尾处输出空格,以达到删除的视觉效果 snake_map[p->x][p->y] = false; //更新蛇身地图 tail = p->suc; //更新蛇尾 tail->pre = NULL; //更新新蛇尾的pre delete p; //回收旧蛇尾占用的内存 --len; //更新蛇身长度 } void SNAKE::PrintSnake() { SNAKE_NODE *p = head; int i = 0; while (p) { SetTextColorToBlue(); print(p->x, p->y, fff[i]^i); ++i; p = p->pre; } } //开始游戏 void work() { ScreenInit(); SNAKE snake; snake.GenerateFood(); while (true) { snake.ChangeDir(getch()); //改变方向(除了第一次要等待用户输入,后来执行到这一行时,保证缓冲区内已有输入) while (kbhit()) //kbhit()返回键盘是否有输入(缓冲区内是否有新字符),且不会吞下输入的字符 getch(); //吞下多余的输入(避免输入间隔快于行走间隔时可连续改变方向引起) while (!kbhit()) //若键盘无输入,则蛇向前走一步 { if (!snake.move()) //若撞墙或撞蛇,则游戏结束 { SetTextColorToRed(); SetCursorPosition(10,21); cout << "Orochimaru's fiancee is dead!"; SetTextColorToRed(); SetCursorPosition(10,23); system("pause"); work(); //输出结果后开始下一轮游戏 return; } int sleep_time = sleep_time_t0 - sleep_time_k * (snake.GetLen() - snake_initila_len); //间隔时间与蛇身长度呈一次函数关系 if (sleep_time < sleep_time_min) sleep_time = sleep_time_min; if (sleep_time > sleep_time_max) sleep_time = sleep_time_max; //但不会超过[min,max]这一范围,避免过快或过慢 Sleep(sleep_time); //注意S要大写 } } } int init() //初始化 { srand(time(0)); //设置随机种子 SetWindow(); //设置窗口 } int main() { init(); cout << "You can control your snake by "; SetTextColorToRed(); cout << "SDWA" << endl; SetTextColorToWhite(); cout << "Please input any key to begin!" << endl; SetCursorPosition(0,0); getch(); //getch()会等待键盘输入(不用按回车键,不会在屏幕上回显输入的字符)返回输入的字符 work(); return 0; } /* int main() { for (int i = 0; i < fff_len; ++i) printf("%d, ", flag[i] ^ i); printf("\n"); return 0; } */ |
左右横移
题目
众所周知,坂本dalao左右横移的速度非常快,你跟得上吗?
附件
答案
HSCTF{girigiri.love}
做法
用StegSolve或者PS这些工具在第30帧即可看见一个二维码
虽然二维码受到了严重损伤,但是微信靠近扫几遍就可以了
与佛论禅
题目
众所周知,凯撒大帝在FGO里变成了一个死肥宅。
对此,人们一直都很好奇。
现在,前方记者得到了采访机会:“是不是打DNF的人都是死肥宅?”
凯撒大帝答曰:“佛曰:礙夷怯提侄藐諳依。漫醯怯故那耨奢想冥都罰一罰謹諸呐離豆曰俱曰俱道吉俱豆冥道罰不罰醯若罰隸遠密究羯藝即奢礙缽帝知皤數切奢吉奢苦缽無呐吉彌俱逝罰智集沙”
答案
HSCTF{Et tu, Brute?}
做法
百度“ctf 与佛论禅”点开第一个,复制进去即可解得DOYPB{Ap pq, Xnqpa?}
之后是一个凯撒密码,由于DOYPB肯定对应于HSCTF,可知是ROT22
拯救大兵艾伦
题目
众所周知,艾伦(eren)身怀坐标之力(flag)可以变身成为巨人(kyojin)
于是,他又双叒叕被抓走啦233
三爷当然是选择原谅,啊呸,救回他
不过救回来的是巨人状态的艾伦,我们需要把他复原回去
附件
答案
HSCTF{zuD~b!qo~zH;~li}
做法
发现f函数是求模p乘法逆元
跟异或一样,把“整容后”再整一次容就可以变回“整容前”
然后问题是连p也未知
不过p一定是素数,候选项不会太多,果断爆破
最后发现p就是193
(有选手的做法是根据结果应该以”HSCTF{“开头而爆破出193,这样的话可以不用看懂f函数)
(早知道flag就不包括”HSCTF{}”,让他们额外补充算了)
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// copy from 地下室.html let f = (x, y) => (x == 1) ? 1 : f(y % x, y) * (y - parseInt(y / x)) % y; let kyojin = "~dyl[fj!XHAu)(Hj~$HT}i"; // get prime const MAXP = 1000000; let prime = new Array(MAXP).fill(0); for (let i = 2; i <= MAXP; ++i) { if (!prime[i]) prime[++prime[0]] = i; for (let j = 1; j <= prime[0] && prime[j] * i <= MAXP; ++j) { prime[prime[j]*i] = 1; if (i % prime[j] == 0) break; } } //try prime for (let i = 1; i <= prime[0]; ++i) { let eren = prime[i]; let flag = []; Array.from(kyojin).forEach(x => { if (x.charCodeAt(0) >= eren) return; let y = f(x.charCodeAt(0), eren); if (y < 33 || y > 126) return; flag.push(y); }); if (flag.length == kyojin.length) { console.log(eren); console.log(flag.map(x => String.fromCharCode(x)).join("")); } } |
我的妹妹不可能这么直男
题目
众所周知,埃罗曼阿老师不敢走出房间,在跟和泉老师“说话”时,采取的是地板语,脚尖碰地的声音较亮为1,脚跟碰地的声音较沉为0。同时为了避免产生误会,埃罗曼阿老师采用了卷积码这种纠错码。有一天,和泉老师向埃罗曼阿老师表白了,正当和泉老师收到回复时,德国骨科老师把和泉老师的型号为“1/2,3”的解码器打断了。隔壁家的山田老师偷偷把声音录了下来,不过她不是直男,只能向你求助:“我很好奇,把埃罗曼阿老师的回复(译码之后)填进HSCTF{}里发给我吧!”
提示
埃罗曼阿老师当然不是心算卷积码的直男,她不知道卷积码适合串行传输,误以为是分组式的纠错码,于是她采取了一个字母编码一次的方式。
附件
答案
HSCTF{H4nt@!}
做法
首先把声音转换成01串(空格为短间隔,换行为长间隔)
00 11 10 11 11 10 11 00 00 00
00 00 11 01 01 00 10 11 00 00
00 11 01 01 00 01 10 01 11 00
00 11 01 10 01 00 10 11 00 00
00 11 10 11 00 00 00 00 00 00
00 00 11 10 11 00 00 11 10 11
谷歌搜索“convolutional code online”第一个就是在线编码器
在页面下方选择参数“R=1/2, K=3”(根据题目暗示)并选择解码器
进入在线解码器,仿照已有的格式,加入”-“间隔符,一行一行地放进去解码,每一行都得到了10位的01串
0100100000
0011010000
0110111000
0111010000
0100000000
0010000100
发现最后两位都是0,根据卷积码的编码原理,很可能是多余的(编码时把寄存器内的数字挤出去)
而且根据提示猜测是ASCII码,只取前8位
01001000
00110100
01101110
01110100
01000000
00100001
解得H4nt@!
众所周知
题目
众所周知,众所周知开头的题目都是我出的,真的是这样吗?
附件
答案
HSCTF{tHe}{c}{pRogRam{MiNN}{LANgua233}
做法
先运行,发现直接输出No,用IDA打开后直接查找“No”字符串,再找到这个字符串出现的位置
但此时发现无法F5显示C代码,证明代码中有异常,导致IDA未能正常解析
浏览一下当前函数的汇编码后就可以发现存在花指令
用IDA的patch功能patch掉花指令,保存后重新加载文件就可以用F5查看C代码了
可以看到C代码之后,认真看代码,可知:
该程序首先对输入的字符串进行映射,得到的结果是个数字数组
然后把这些数字作为系数,对多项式进行离散傅里叶变换,得到的结果是个复数数组
然后强行对该复数数组的内存空间进行base64,得到的结果是个字符串,即key
所以,简单地逐步逆向回去就可以得到flag:
VlRCYVQxSkdXa1pYYW1SclVsZG9jMXBzYURCaGJWcFpaRWhrVm1KVWJIVldWekZIWkVkVmQwMVlRbFZoZWxVMVdsUkNORkZzVW5SYVJFWmFWa1ZzTmxSVVRYZFFVVDA5
但这不是真正的flag,还需要base64解码5次(增加长度,防止强行爆破flag)
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
#include <bits/stdc++.h> char key[] = "aaaaaadBSeaaaaaaaaaaahBqhonnEgLaLaglsFEZPmcF67OkL61SqgBWSMuCxwhaXepXQeUrp0dO8ggnKdsrWddnUhI6redaSLUPCem4p8bjpEH3eZToqdZnASLiw4lalLJgmzLbp8aMsn4B76eGWmv74ge5Egba5M0A9NDKDmdcjb30j25yqbs9GXSfvMdaaclYwJ{f47{V0VKVz2jYWfS2y4LJAMLaaoaFcYwOrSbGOU02Ub1gqiUYX6SjjOdaHgj7M9YaySaae7sL{PTCWf}ko4EFx03afA4{BRrTACbmp8li}Z1eWdNmvXVDw1BaefCyEPbVBScul1krA1rFWetnDzSOk1La0aSGr998CKa{FTGZB5LMqhwqLT5EhhdaaccDLFXZl0cmbEM0xTSWWcd41Gsp8c7aSsM49eq{CCdiRMRYFmrwWl9NnZnv4wjazpRmcyHSy0aHSeCNSoHRWa{Igx9iR2Ra}eoxGWggrecdf{XXSyLJqabgAWvBPVq}6TxhKbbRumd0{C0Jr4O2WkY}n6Wl6LTa8vBIhXk{p8cIM0CoVY9IWkbW2MmaGGrancOi20Uvz0c96cT9JXrVqdo4GslWhhjaANyHQgfHySbGi7b1e6nlqgYMQhhMFglasaG0vOTiuKdh{qUv0FjGWkRHl9Pbme3aSpHRYmcYvmdGuJAawV9Eqed4YqlkIr5axomke}gHmKdSNGvCgrnRWgWmhHHZd03a93vhKrOwqudsLMIorkDHqmI}p6tqGLRaAQDKeBbkvSdg6yUhYMbHWml7txl4bdnaqae1Hv7fhKd4MOStHfqWWdkAvNZVvwFaCKDbSZl2A8ay18DD57TbqlwW{QI{E1bapoCZQoWhyedqkXzd36WIWpQp136PedZa4Q{9rRiYqecyRYiEDbfwqe}prC19Wfja8gGaZ3LGoebwJGjKW4rHqhIyu{OhbKVa9nXhhjpUxSbO0jj3EdDBWorxZTygwK1aF1Mm64EyA0aMAPMrl5vMqjO3czm7QMdawgz0EnSkr8di9YfunGCrqhRJCMaJi2naZpIrWydrq8cKh}BZr0nhWlYH6DbvFgpaUO8NyZMKvCa8PhNOdzbrqj16Ry3nP2bavbOroKwco0byXAAi4yK3Wab09XjLcghayuDZTW6zuCaHnFgonV1fqhc5qXVbWX}aao2272HZo0dWqJOSxUGOqiQW9TCX5eXaGn1D0PjUcebKNfoVkDG4qmtVwWZiJZPa2wNRBPB7uedacKRTkXCkWeTaSroZKLfaMOU1iz0dy0brO5Igh}zFqc4CjMG80vnaF9cO5r6{v8ca44N2H8elWoa37QhkWLzahoXBIekzwudsBbI{nHC5qp3}}}}}F09acaaaaaaauKaC{RJ39m9JqcP5LoNJJubamaLAQmRzyec8Kqpc7w1rWd5sMpSNFdtaKecXCliEo8baGNi1FDTNqmh0UhEIyLfaagQw0rT5imdsMH0LgG1VWo2M67UAvwlaz1ZkTUnTBKcU}FOT3l1ZqlYE1HRkivTapc{ZGV9uzua0JYlw7Q9wWhblSq8D5vPad7KD108JzSctImUG6cfBWkINtSILrI3avOFaxE8pzebVeT6{gFvrqebR3e3YktLa1I719sB0xSbSBvEz6KzcqntLukUu4wfaZOwom2MTC0b6AqeZ9}zrWgZRegUu2JfalbxbtSm4Cmd0rXQf5xmHWkWRo6gEs1xahZpy6AuNxCdSz5n5Lf9OWh6az62Qt3da}}v{5WUPy0bmllCxGwHJqfQDiL14nhbaPHDuCQdbzecqBqUExzjxWhPHN7LAFfBazXnRQBW6s0bcdOAItHrQqktH3MzDLgzaScjcq3csA0cE5LL4JEbxWokTVXNvC1Ha89hC61wBxSaaxVdwKGudqaBZ6pUBmtBaaLLeKJ33B0ck1csn9FLlWdryaBg}{fpaPUzJ}pb{DmdFYGeiJNjzWdiFn4VdW1za9x2xgT}qsecM3J3jP5zmWiZEmqnqCvraSOBtXXBprmb8hkokqJLNWobuOKFw8hhaWjqnOnB}CmdLjWSOj9PZqnX1I7sOuwfasrFXAqXMvKb4vcZYW4PgWlVtYiFeAw9aIkxnLjvGEecgaOVYTkjoqdc6KysmXsnapeKVto{1yCdFprijRZjxqlA8{iaF2eTa7tytIByktKb8I{l}QnSZWfQ{imwyRMbajTP2Ey7Bs0d3dfb6Y2rPqhETbuv}v1lalUG7NdQvwKb4VbmplRvRWeUAjP{2o13aMUJRusuqz8bVwQQJolvLWj4{Sgys{0jamnwioIw2kudUZXgsE1zLqmOM5rodhwnav6KXRgbduecvTLgidFfLqiCot}aVdv}a9AHCBgGjzCduujx4MtfKWfkImf187KdaiNibI7vlA0aAIaieH}fBqfsg0SGWAYjaX2QJLPBpyua9zMV3B2q9qch90guuQfRae0bJcvcvz8cGrW1NpoaKqpe{BDihihTa0bfzULjWFuaMFI005r9TWlQlfiRcm2BaqG8M7BKIwCbC0YkwdSnOqloisfn3vfRaLLTNoDpGCSbm8pi40nDBWmceheHYouTaA6LjKcqZCebcvgBueyTBqj0SO7utJtjaeqVknwsfyeaGmQ4yamq1Wlu0UmSg9cFaBs2IafHJoScW8c4JxCLEqgcMh9OGw0jaJx}aWS6cv0ceeipkSCzsWdYmWo8VOd5aekef{ORTzCaaaaaaacbRWaaaaaaaaaaabiZa7Y{GpKb4Oax6IU1Lqj5}WmloGLDazXcdYRhguKcx8c4JxCLEqhcNh9OGw0laVJs4YWB0j8bclAiawgm6qailYJvKHwbaedgUgadenuaWvgBueyTBqg0SO7utJtla3yqCshi5s0bQQuMqjdnWWiHBzZNt4hlaj}dYondxw0bm0YkwdSnOqiEisfn3vfPaP4SuISiZzSaSdYBTUsjzql4rwBPsCh1ach4TnouFBucarW1NpoaKqoq{BDihihVagV3qzrsOwSd9p2mjujvNql5QO5AwZ2fax2zR929KpCd0HWieH}fBqbYg0SGWAYlakkiWxxZUqmamCGglTuTRWoYOxgXOcwxaWLcv{jKXzeckTLgidFfLqiuot}aVdv9aXIBLe4mDy0bDQtgSyenqWbZvIdOLTILa5C8rKNTwzCbKwQQJolvLWlW{Sgys{0lauPOMN7y7xCcu6oTrjrbNqcROo5W6LvPaClWtdY61A0dXdfb6Y2rPqgYTbuv}v1javB4GXzIUyea02Nz5JTTlWmO2e4M2cK5aPiVI}6JBm0d}prijRZjxqkY8{iaF2eVaqlQrHiZfi0aWss9m77vHqiALZzsvyhHaFGkl8RsItSbJvcZYW4PgWmhtYiFeAw}a2hwlTkHryubOf}fPdgzwWlIudAdw}3da4YClkcFAC8b2hkokqJLNWm9uOKFw8hfaIn4Xa1bXvecPHTphfS9eqpL9LXRF0eHaIn49YAEwtedwYGeiJNjzWdmFn4VdW1BalfGbSB}4u8cD5Mp88h50qpLyrji9929aETqKJFx5s0cGxpdwKGudqoJY6pUBmtza362}gDvZwed40DZRvzTEqkGIqKnWKMTaLozzEi3Gv0bcdOAItHrQqjJH3MzDLgBaz2gFUvP8vSb{e2UPVdPlWkixvhkGWwraJg0lNL2sv0bgllCxGwHJqfIDiL14nhdaEObNRAPpCmd79x7Nc6LJWbCZ2oMLj13a5MEtEzrFAebgsbQf5xmHWkORo6gEs1vapoSqA5tAmuaUfCfoWZHWqmYfJJnPRxnaIgKbm}F2uucdBvEz6KzcqnlLukUu4whasgVCtFiPoudplVx1jVrEqfMhWf3Vd2raCHlEVHN1uCcDImUG6cfBWesNtSILrI1aB0UXdX3LwKaxUr3xtYnMqd8VS4l}vgvao48I1U6VvKcW}FOT3l1ZqlwE1HRkivVa6kBRU5PvySbSxmQ2421UWbbQLTeBEsda1jODjrOnB0bgGNi1FDTNqmp0UhEIyLhaqLky{YD8nma8qlfWSH47qdijwQJk2wbaYjedWU1Tuubc{RJ39m9JqiL5LoNJJudaaWaaaacat0aiaaaaaabsWghSw4HcMvLaK20yVJyxoCbG44N2H8elWnG37QhkWLBamHWMAdZru0bS0kJLhR5xqjAlTsgDa2nar6oyHH}2x8caceRTkXCkWeXaSroZKLha{U9BdmIpoKdIAETULVTqWmdDxDksBGHaWjXtRYNyomaiqZOSxUGOqisW9TCX5eZa8lHdg8hdh8aq7BBVAhm7Wf1hC7CoMvhafZxXJJB9rCbuXAAi4yK3WpXZ9XjLcgfaMhQTJC2NyebAgHe6ryi7WlQpj2m5Pfxaqkr56a2quCdah}BZr0nhWlwH6DbvFgnaConYycmJy0dS{jhbGnfdqgnMDhJBcKFaMpCHvdyheCaOAPMrl5vMqkO3czm7QMbaffJo1GzAtuchwyZRH5HRWpZCrXYt7L7awncsD3G3w0buJGjKW4rHqicyu{OhbKTavm9fZx3auKd{AadpEwa4WnQVVuAYmKbaOA8IhNqrvSd4kXzd36WIWpIp136PedXaTRd6Ql57uea{5ZoO7aDGWhDhqBmY9MVaiDFhxEE7qCaSM4StHfqWWdAAvNZVvwDa6VTnCVGem0aGadwfxSuEWgENzbgWsLBaY{MlH8PGyudGLMIorkDHqm2}p6tqGLPaGqWEghmptCacDKErgHzbWgtKcHpXOtja9z4fxbKtA0d{uJAawV9Eqmd4YqlkIr7aq{eV2KeWtCct{gViWljuqfKinfAlsfjaYFKlLDhYyebCi7b1e6nlqgkMQhhMFgjanlIbiVaCCKb0DIgOywfIqeiQcnTlLwDaYoGRFy8uB8cRM0CoVY9IWobX2MmaGGtaSB83RaVQw0dBvUiFeR4}qpRvX5aqA1da}pNni0EknKchf{XXSyLJqma}AWvBPVs}ekizF0IVASdMq5EdayzeWhh6ZaMiBgnalRbhj7dOA0dmRMRYFmrwWm5NnZnv4wla4pJwbi}WlSc0kBJ0rd5XqnaFNzx8CY9aPaxPTf7BmeaZFTGZB5LMqicqLT5EhhbaxC11MYGRwudBcYbh33XYWdTxghQqB27aLI9sKwTux0cmp8li}Z1eWepmvXVDw1zaHSO7H59FtCaPRJ5UTg1Pqi5IE5VCGgla7bk0PFQBxedGOE02Ub1gqjsYX6SjjObaCdzJIwnQAuaR4b8ljAHgqiaW8LO}HEo}T9l5l2DICKdQjb30j25yqcI9GXSfvMbaYNVGytL4yedXBrR2D2r0qgHyXJgzqt}anKJEg{{HieaRpEH3eZToqeRnASLiw4jat824ElPeqmcLw6LWqZG}qbjd8AHlKt9a9pbHJza0KucU67OkL61SqhFWSMuCxwfaznaC4014AucHayTj97oKqaaa"; const double P = acos(-1.0); struct C { double x = 0.0, y = 0.0; C() = default; C(double _x, double _y) : x(_x), y(_y) {} }; C operator - (const C &a, const C &b) { return C(a.x-b.x, a.y-b.y); } C operator + (const C &a, const C &b) { return C(a.x+b.x, a.y+b.y); } C operator * (const C &a, const C &b) { return C(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x); } void ch(C *y, int l) { for (int i = 1, j = l / 2; i < l - 1; ++i) { if (i < j) std::swap(y[i], y[j]); int k = l / 2; while (j >= k) { j -= k; k /= 2; } if (j < k) j += k; } } void F(C *y, int l) { ch(y, l); for (int h = 2; h <= l; h <<= 1) { C wn(cos(-2 * P / h), sin(-2 * P / h)); for (int j = 0; j < l; j += h) { C w(1, 0); for (int k = j; k < j + h / 2; ++k) { C u = y[k]; C t = w * y[k + h / 2]; y[k] = u + t; y[k + h / 2] = u - t; w = w * wn; } } } return; } char m1[64] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '{', '}'}; char m2[233]; const int MAXN = 666; char a[MAXN]; C x[MAXN]; unsigned char xx[MAXN * 16]; char s[MAXN * 16]; int main() { for (char i = 'a'; i <= 'z'; ++i) m2[i] = i - 'a'; for (char i = 'A'; i <= 'Z'; ++i) m2[i] = i - 'A' + 26; for (char i = '0'; i <= '9'; ++i) m2[i] = i - '0' + 52; m2['{'] = 62; m2['}'] = 63; freopen("flag", "r", stdin); scanf("%s", a); int la = strlen(a); int lx = la << 1; for (int i = 0; i < lx; ++i) x[i] = i < la ? C(m2[a[la - 1 - i]], 0) : C(0, 0); F(x, lx); memcpy(xx, x, lx * 16); for (int i = 0, j = 0; i < lx*16 + 2; ) { uint32_t ua = xx[i++]; uint32_t ub = xx[i++]; uint32_t uc = xx[i++]; uint32_t uu = (ua << 16) + (ub << 8) + uc; s[j++] = m1[(uu >> 18) & 0x3f]; s[j++] = m1[(uu >> 12) & 0x3f]; s[j++] = m1[(uu >> 6) & 0x3f]; s[j++] = m1[uu & 0x3f]; } if (!strcmp(s, key)) puts("YES"); else puts("NO"); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
#include <bits/stdc++.h> char key[] = "aaaaaadBSeaaaaaaaaaaahBqhonnEgLaLaglsFEZPmcF67OkL61SqgBWSMuCxwhaXepXQeUrp0dO8ggnKdsrWddnUhI6redaSLUPCem4p8bjpEH3eZToqdZnASLiw4lalLJgmzLbp8aMsn4B76eGWmv74ge5Egba5M0A9NDKDmdcjb30j25yqbs9GXSfvMdaaclYwJ{f47{V0VKVz2jYWfS2y4LJAMLaaoaFcYwOrSbGOU02Ub1gqiUYX6SjjOdaHgj7M9YaySaae7sL{PTCWf}ko4EFx03afA4{BRrTACbmp8li}Z1eWdNmvXVDw1BaefCyEPbVBScul1krA1rFWetnDzSOk1La0aSGr998CKa{FTGZB5LMqhwqLT5EhhdaaccDLFXZl0cmbEM0xTSWWcd41Gsp8c7aSsM49eq{CCdiRMRYFmrwWl9NnZnv4wjazpRmcyHSy0aHSeCNSoHRWa{Igx9iR2Ra}eoxGWggrecdf{XXSyLJqabgAWvBPVq}6TxhKbbRumd0{C0Jr4O2WkY}n6Wl6LTa8vBIhXk{p8cIM0CoVY9IWkbW2MmaGGrancOi20Uvz0c96cT9JXrVqdo4GslWhhjaANyHQgfHySbGi7b1e6nlqgYMQhhMFglasaG0vOTiuKdh{qUv0FjGWkRHl9Pbme3aSpHRYmcYvmdGuJAawV9Eqed4YqlkIr5axomke}gHmKdSNGvCgrnRWgWmhHHZd03a93vhKrOwqudsLMIorkDHqmI}p6tqGLRaAQDKeBbkvSdg6yUhYMbHWml7txl4bdnaqae1Hv7fhKd4MOStHfqWWdkAvNZVvwFaCKDbSZl2A8ay18DD57TbqlwW{QI{E1bapoCZQoWhyedqkXzd36WIWpQp136PedZa4Q{9rRiYqecyRYiEDbfwqe}prC19Wfja8gGaZ3LGoebwJGjKW4rHqhIyu{OhbKVa9nXhhjpUxSbO0jj3EdDBWorxZTygwK1aF1Mm64EyA0aMAPMrl5vMqjO3czm7QMdawgz0EnSkr8di9YfunGCrqhRJCMaJi2naZpIrWydrq8cKh}BZr0nhWlYH6DbvFgpaUO8NyZMKvCa8PhNOdzbrqj16Ry3nP2bavbOroKwco0byXAAi4yK3Wab09XjLcghayuDZTW6zuCaHnFgonV1fqhc5qXVbWX}aao2272HZo0dWqJOSxUGOqiQW9TCX5eXaGn1D0PjUcebKNfoVkDG4qmtVwWZiJZPa2wNRBPB7uedacKRTkXCkWeTaSroZKLfaMOU1iz0dy0brO5Igh}zFqc4CjMG80vnaF9cO5r6{v8ca44N2H8elWoa37QhkWLzahoXBIekzwudsBbI{nHC5qp3}}}}}F09acaaaaaaauKaC{RJ39m9JqcP5LoNJJubamaLAQmRzyec8Kqpc7w1rWd5sMpSNFdtaKecXCliEo8baGNi1FDTNqmh0UhEIyLfaagQw0rT5imdsMH0LgG1VWo2M67UAvwlaz1ZkTUnTBKcU}FOT3l1ZqlYE1HRkivTapc{ZGV9uzua0JYlw7Q9wWhblSq8D5vPad7KD108JzSctImUG6cfBWkINtSILrI3avOFaxE8pzebVeT6{gFvrqebR3e3YktLa1I719sB0xSbSBvEz6KzcqntLukUu4wfaZOwom2MTC0b6AqeZ9}zrWgZRegUu2JfalbxbtSm4Cmd0rXQf5xmHWkWRo6gEs1xahZpy6AuNxCdSz5n5Lf9OWh6az62Qt3da}}v{5WUPy0bmllCxGwHJqfQDiL14nhbaPHDuCQdbzecqBqUExzjxWhPHN7LAFfBazXnRQBW6s0bcdOAItHrQqktH3MzDLgzaScjcq3csA0cE5LL4JEbxWokTVXNvC1Ha89hC61wBxSaaxVdwKGudqaBZ6pUBmtBaaLLeKJ33B0ck1csn9FLlWdryaBg}{fpaPUzJ}pb{DmdFYGeiJNjzWdiFn4VdW1za9x2xgT}qsecM3J3jP5zmWiZEmqnqCvraSOBtXXBprmb8hkokqJLNWobuOKFw8hhaWjqnOnB}CmdLjWSOj9PZqnX1I7sOuwfasrFXAqXMvKb4vcZYW4PgWlVtYiFeAw9aIkxnLjvGEecgaOVYTkjoqdc6KysmXsnapeKVto{1yCdFprijRZjxqlA8{iaF2eTa7tytIByktKb8I{l}QnSZWfQ{imwyRMbajTP2Ey7Bs0d3dfb6Y2rPqhETbuv}v1lalUG7NdQvwKb4VbmplRvRWeUAjP{2o13aMUJRusuqz8bVwQQJolvLWj4{Sgys{0jamnwioIw2kudUZXgsE1zLqmOM5rodhwnav6KXRgbduecvTLgidFfLqiCot}aVdv}a9AHCBgGjzCduujx4MtfKWfkImf187KdaiNibI7vlA0aAIaieH}fBqfsg0SGWAYjaX2QJLPBpyua9zMV3B2q9qch90guuQfRae0bJcvcvz8cGrW1NpoaKqpe{BDihihTa0bfzULjWFuaMFI005r9TWlQlfiRcm2BaqG8M7BKIwCbC0YkwdSnOqloisfn3vfRaLLTNoDpGCSbm8pi40nDBWmceheHYouTaA6LjKcqZCebcvgBueyTBqj0SO7utJtjaeqVknwsfyeaGmQ4yamq1Wlu0UmSg9cFaBs2IafHJoScW8c4JxCLEqgcMh9OGw0jaJx}aWS6cv0ceeipkSCzsWdYmWo8VOd5aekef{ORTzCaaaaaaacbRWaaaaaaaaaaabiZa7Y{GpKb4Oax6IU1Lqj5}WmloGLDazXcdYRhguKcx8c4JxCLEqhcNh9OGw0laVJs4YWB0j8bclAiawgm6qailYJvKHwbaedgUgadenuaWvgBueyTBqg0SO7utJtla3yqCshi5s0bQQuMqjdnWWiHBzZNt4hlaj}dYondxw0bm0YkwdSnOqiEisfn3vfPaP4SuISiZzSaSdYBTUsjzql4rwBPsCh1ach4TnouFBucarW1NpoaKqoq{BDihihVagV3qzrsOwSd9p2mjujvNql5QO5AwZ2fax2zR929KpCd0HWieH}fBqbYg0SGWAYlakkiWxxZUqmamCGglTuTRWoYOxgXOcwxaWLcv{jKXzeckTLgidFfLqiuot}aVdv9aXIBLe4mDy0bDQtgSyenqWbZvIdOLTILa5C8rKNTwzCbKwQQJolvLWlW{Sgys{0lauPOMN7y7xCcu6oTrjrbNqcROo5W6LvPaClWtdY61A0dXdfb6Y2rPqgYTbuv}v1javB4GXzIUyea02Nz5JTTlWmO2e4M2cK5aPiVI}6JBm0d}prijRZjxqkY8{iaF2eVaqlQrHiZfi0aWss9m77vHqiALZzsvyhHaFGkl8RsItSbJvcZYW4PgWmhtYiFeAw}a2hwlTkHryubOf}fPdgzwWlIudAdw}3da4YClkcFAC8b2hkokqJLNWm9uOKFw8hfaIn4Xa1bXvecPHTphfS9eqpL9LXRF0eHaIn49YAEwtedwYGeiJNjzWdmFn4VdW1BalfGbSB}4u8cD5Mp88h50qpLyrji9929aETqKJFx5s0cGxpdwKGudqoJY6pUBmtza362}gDvZwed40DZRvzTEqkGIqKnWKMTaLozzEi3Gv0bcdOAItHrQqjJH3MzDLgBaz2gFUvP8vSb{e2UPVdPlWkixvhkGWwraJg0lNL2sv0bgllCxGwHJqfIDiL14nhdaEObNRAPpCmd79x7Nc6LJWbCZ2oMLj13a5MEtEzrFAebgsbQf5xmHWkORo6gEs1vapoSqA5tAmuaUfCfoWZHWqmYfJJnPRxnaIgKbm}F2uucdBvEz6KzcqnlLukUu4whasgVCtFiPoudplVx1jVrEqfMhWf3Vd2raCHlEVHN1uCcDImUG6cfBWesNtSILrI1aB0UXdX3LwKaxUr3xtYnMqd8VS4l}vgvao48I1U6VvKcW}FOT3l1ZqlwE1HRkivVa6kBRU5PvySbSxmQ2421UWbbQLTeBEsda1jODjrOnB0bgGNi1FDTNqmp0UhEIyLhaqLky{YD8nma8qlfWSH47qdijwQJk2wbaYjedWU1Tuubc{RJ39m9JqiL5LoNJJudaaWaaaacat0aiaaaaaabsWghSw4HcMvLaK20yVJyxoCbG44N2H8elWnG37QhkWLBamHWMAdZru0bS0kJLhR5xqjAlTsgDa2nar6oyHH}2x8caceRTkXCkWeXaSroZKLha{U9BdmIpoKdIAETULVTqWmdDxDksBGHaWjXtRYNyomaiqZOSxUGOqisW9TCX5eZa8lHdg8hdh8aq7BBVAhm7Wf1hC7CoMvhafZxXJJB9rCbuXAAi4yK3WpXZ9XjLcgfaMhQTJC2NyebAgHe6ryi7WlQpj2m5Pfxaqkr56a2quCdah}BZr0nhWlwH6DbvFgnaConYycmJy0dS{jhbGnfdqgnMDhJBcKFaMpCHvdyheCaOAPMrl5vMqkO3czm7QMbaffJo1GzAtuchwyZRH5HRWpZCrXYt7L7awncsD3G3w0buJGjKW4rHqicyu{OhbKTavm9fZx3auKd{AadpEwa4WnQVVuAYmKbaOA8IhNqrvSd4kXzd36WIWpIp136PedXaTRd6Ql57uea{5ZoO7aDGWhDhqBmY9MVaiDFhxEE7qCaSM4StHfqWWdAAvNZVvwDa6VTnCVGem0aGadwfxSuEWgENzbgWsLBaY{MlH8PGyudGLMIorkDHqm2}p6tqGLPaGqWEghmptCacDKErgHzbWgtKcHpXOtja9z4fxbKtA0d{uJAawV9Eqmd4YqlkIr7aq{eV2KeWtCct{gViWljuqfKinfAlsfjaYFKlLDhYyebCi7b1e6nlqgkMQhhMFgjanlIbiVaCCKb0DIgOywfIqeiQcnTlLwDaYoGRFy8uB8cRM0CoVY9IWobX2MmaGGtaSB83RaVQw0dBvUiFeR4}qpRvX5aqA1da}pNni0EknKchf{XXSyLJqma}AWvBPVs}ekizF0IVASdMq5EdayzeWhh6ZaMiBgnalRbhj7dOA0dmRMRYFmrwWm5NnZnv4wla4pJwbi}WlSc0kBJ0rd5XqnaFNzx8CY9aPaxPTf7BmeaZFTGZB5LMqicqLT5EhhbaxC11MYGRwudBcYbh33XYWdTxghQqB27aLI9sKwTux0cmp8li}Z1eWepmvXVDw1zaHSO7H59FtCaPRJ5UTg1Pqi5IE5VCGgla7bk0PFQBxedGOE02Ub1gqjsYX6SjjObaCdzJIwnQAuaR4b8ljAHgqiaW8LO}HEo}T9l5l2DICKdQjb30j25yqcI9GXSfvMbaYNVGytL4yedXBrR2D2r0qgHyXJgzqt}anKJEg{{HieaRpEH3eZToqeRnASLiw4jat824ElPeqmcLw6LWqZG}qbjd8AHlKt9a9pbHJza0KucU67OkL61SqhFWSMuCxwfaznaC4014AucHayTj97oKqaaa"; const double P = acos(-1.0); struct C { double x = 0.0, y = 0.0; C() = default; C(double _x, double _y) : x(_x), y(_y) {} }; C operator - (const C &a, const C &b) { return C(a.x-b.x, a.y-b.y); } C operator + (const C &a, const C &b) { return C(a.x+b.x, a.y+b.y); } C operator * (const C &a, const C &b) { return C(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x); } void ch(C *y, int len) { for (int i = 1, j = len / 2; i < len - 1; ++i) { if (i < j) std::swap(y[i], y[j]); int k = len / 2; while (j >= k) { j -= k; k /= 2; } if (j < k) j += k; } } void reF(C *y, int len) { ch(y, len); for (int h = 2; h <= len; h <<= 1) { C wn(cos(2 * P / h), sin(2 * P / h)); for (int j = 0; j < len; j += h) { C w(1, 0); for (int k = j; k < j + h / 2; ++k) { C u = y[k]; C t = w * y[k + h / 2]; y[k] = u + t; y[k + h / 2] = u - t; w = w * wn; } } } for (int i = 0; i < len; ++i) y[i].x /= len; } int m1[64] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '{', '}'}; int m2[233]; const int MAXN = 666; char a[MAXN]; C x[MAXN]; unsigned char xx[MAXN * 16]; char s[MAXN * 16]; int main() { for (char i = 'a'; i <= 'z'; ++i) m2[i] = i - 'a'; for (char i = 'A'; i <= 'Z'; ++i) m2[i] = i - 'A' + 26; for (char i = '0'; i <= '9'; ++i) m2[i] = i - '0' + 52; m2['{'] = 62; m2['}'] = 63; int ls = strlen(key); for (int i = 0, j = 0; i < ls; ) { uint32_t ua = m2[key[i++]]; uint32_t ub = m2[key[i++]]; uint32_t uc = m2[key[i++]]; uint32_t ud = m2[key[i++]]; uint32_t uu = (ua << 18) + (ub << 12) + (uc << 6) + ud; xx[j++] = (uu >> 16) & 0xFF; xx[j++] = (uu >> 8) & 0xFF; xx[j++] = uu & 0xFF; } int lx = ((ls / 4) * 3 - 2) / 16; memcpy(x, xx, lx * 16); reF(x, lx); for (int i = 0; i < lx; ++i) a[i] = (int)(x[i].x + 0.5); int la = lx; while (a[la] <= 0 && la > 0) --la; for (int i = la; i >= 0; --i) printf("%c", m1[a[i]]); return 0; } |