给你一个初始串"MI",这个串有三种操作,
(1)M后卖弄可以直接复制 ,MI -> MII
(2)三个III可以变成一个U,MUIII -> MUU
(3)连续的两个U可以直接删除,MIUUU -> MIU
每次输入一个字符串,问你这个字符串是不是MI变过来的.
思路:
刚开始想都没想直接开个容器mark,然后搜索打表,控制的长度是1000000,直接敲完运行等了好几分钟都没打完,哎! sb了,后来仔细看了看题目发现 其实我们可以这样想,所有的U都是i经过一线变化过来的,因为刚开始的时候没有U,而i能变成u而u不能变成i,还有的就是这个串一定是开头是M,因为没有操作能让中间产生m,或者把M变没,这样就简单了,那么就相当于一开始有一个i,我们可以把i的个数*2(操作1) 或者把i的个数-6 (操作3),这样所有的可能i的个数都打出来,没多少1--300000个,对于输入的串我们先看下是不是只有开头有一个M,然后在统计下他有多少个i,一个u是三个i(还原操作2),然后根据当前的i的数量是否被mark输出Yes或者No,水题一枚.
#include<stdio.h> #include<string.h> #define N 1000100 char str[N]; int mark[N*3]; void DFS(int s) { mark[s] = 1; if(s * 2 <= N * 3 && !mark[s * 2]) DFS(s * 2); if(s - 6 >= 1 && !mark[s - 6]) DFS(s - 6); } int main () { memset(mark ,0 ,sizeof(mark)); DFS(1); int L ,ms ,t ,sum; scanf("%d" ,&t); while(t--) { scanf("%s" ,str); L = strlen(str); ms = sum = 0; for(int i = 0 ;i < L ;i ++) { if(str[i] == 'M') ms ++; if(i) { if(str[i] == 'I') sum ++; else sum += 3; } } if(ms != 1 || str[0] != 'M' || !mark[sum]) puts("No"); else puts("Yes"); } return 0; }