17999 Light-bot 模拟 + kmp求循环节
http://acm.scau.edu.cn:8000/uoj/mainMenu.html
17999 Light-bot
时间限制:1000MS 内存限制:65535K
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定
Description
I (you needn't know who am "I".) am currently playing a game called "Light-bot". In the game, the "Light-bot" is controlled
by a program. The program includes:
(1) The main procedure. The main procedure is the entrance of the program, same as the "main" in C/C++.
(2) Sub procedure #1. Sub procedure No.1.
(3) Sub procedure #2. Sub procedure No.2.
Note: If a sub procedure ends, it will return to the command next to it's calling place.
Here, we suggest that an alphabetical letter stands for an ACTION COMMAND excluding ‘P’ and ‘p’.
So, "Light-bot" will begin executing from the first command in the main procedure. Once it meets with a letter ‘P’, it will call sub
procedure #1, while a letter ‘p’ indicates to call sub procedure #2. The main procedure, procedure #1 and procedure #2 can call
procedure #1 or procedure #2 freely. It means that recursive calls are possible.
Now, I just want to know given a program, what’s the Nth ACTION COMMAND light-bot will execute.
输入格式
The first line of the input contains an integer T (T <= 1000), indicating there are T cases in the input file.
For each test case, the first line is the main procedure. The second one is sub procedure #1 and the last is sub procedure #2. Each
procedure ends with a ‘#’ sign, which is not considered a command. The length of a part will not exceed 10.
And on the next line, there is one integer n (1 <= n <= 108), indicates the order I ask. It is GUARANTEED that there must be an ACTION COMMAND
fitting the requirement.
Please see the example for more details.
输出格式
For each case, print one line, the ACTION COMMAND letter that fits the description.
输入样例
4
ABCDP#
pEFG#
HIJK#
4
ABCDP#
pEFG#
HIJK#
5
ABCDP#
pEFG#
HIJK#
9
ABCDP#
EFGHP#
#
12
输出样例
D
H
E
H
来源
Lrc_seraph
首先因为其最大的数量是1000(不循环的话)
那么我可以暴力模拟2000次,然后得到一个序列。这个序列的后边肯定是循环的了。
就是XXXXABCABCABC....这样。
然后可以反向kmp一次,求循环节的时候,要从第100项开始,
原因是:
1、第100项开始,求到的循环节长度是一样的,
2、防止AAAA这些假循环节的干扰。
坑了我很久的就是模拟的时候,我模拟到up步,但是取了等号,模拟了UP + 1步。然后一直wa
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> char str[4][20]; char Ma[20]; int len[5]; int lenMa; const int up = 2000 + 20; char all[up + 20]; int lenall = 0; char sub[up + 20]; int lensub = 0; void dfs(int now, int cur) { if (lenall >= up) return; for (int i = cur; i <= len[now] && lenall < up; ++i) { if (str[now][i] == 'P') { dfs(0, 1); } else if (str[now][i] == 'p') { dfs(1, 1); } else all[++lenall] = str[now][i]; } } int tonext[up + 20]; void kmp() { int i = 1, j = 0; tonext[1] = 0; while (i <= lensub) { if (j == 0 || sub[i] == sub[j]) { tonext[++i] = ++j; } else j = tonext[j]; } } void work() { scanf("%s", Ma + 1); for (int i = 0; i <= 1; ++i) { scanf("%s", str[i] + 1); len[i] = strlen(str[i] + 1); len[i]--; } lenMa = strlen(Ma + 1); lenMa--; lenall = 0; for (int i = 1; i <= lenMa && lenall < up; ++i) { //这个up不能去等号 if (Ma[i] == 'P') { dfs(0, 1); } else if (Ma[i] == 'p') { dfs(1, 1); } else { all[++lenall] = Ma[i]; } } all[lenall + 1] = '\0'; int val; scanf("%d", &val); if (val <= up) { printf("%c\n", all[val]); return; } lensub = 0; for (int i = lenall; i >= 1; --i) { sub[++lensub] = all[i]; } sub[lensub + 1] = '\0'; kmp(); // cout << sub + 1 << endl; int cir = 0; // cout << all + 1 << endl; for (int i = 1000 + 20; i <= lensub; ++i) { if (tonext[i + 1] == 1) continue; int t = i - (tonext[i + 1] - 1); if (i % t == 0) { cir = t; // cout << i << endl; break; } } // cout << cir << endl; if (cir == 0) while(1); int left = val - up; left %= cir; if (left == 0) left = cir; int point = lenall - cir + left; printf("%c\n", all[point]); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; scanf("%d", &t); while (t--) work(); return 0; }
posted on 2016-11-10 22:03 stupid_one 阅读(508) 评论(0) 编辑 收藏 举报