解题报告:有一个字符串“MI”,现在定义三种操作,
1:M后面的字符串整体重复一遍,例如MUI可以转换成:MUIUI
2:三个连续的III可以转化成一个U
3:两个连在一起的UU可以去掉
然后输入一个字符串,问MI能否通过若干步的操作转化成输入的这个字符串,可以的话输出Yes,否则输出No
首先第一步M后面只有一个I,所以只能做第一种操作,变成MII也可以一直做下去,这样M后面的I的个数就是2^n个,然后又可以把任意三个III转化成U,这样U就出现了,然后就可以进行去掉两个连续的U的操作了,我的做法是将输入的字符串先扫一遍,然后统计其中有多少个I和U,然后可以确定的是U和I的顺序可以任意,所以我们就可以把所有的U转化成I来一起统计,这样就可以更加方便统计了,然后如果是纯I的话,可能的个数就是2^n次方,再加上去掉UU的,去掉一个UU相当于去掉六个I,于是我们就可以看完全转化成I的个数能否和可能的I的个数相等就可以判断出来了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn = 1000005; 6 int prim[1000],num; 7 char S[maxn]; 8 void dabiao() { 9 int c = 1,i; 10 for(i = 0;c<=1000000;++i) { 11 prim[i] = c; 12 c = c<<1; 13 } 14 prim[i] = c; 15 num = i+1; 16 } 17 int main() { 18 int T; 19 dabiao(); 20 scanf("%d",&T); 21 while(T--) { 22 scanf("%s",S); 23 if(S[0]!= 'M') { 24 printf("No "); 25 continue; 26 } 27 int Un = 0,In = 0; 28 int len = strlen(S),f = 1; 29 for(int i = 1;i<len;++i) 30 if(S[i] == 'U') 31 Un++; 32 else if(S[i] == 'I') 33 In++; 34 else if(S[i] != 'I' && S[i] != 'U') { 35 printf("No "); 36 f = 0; 37 break; 38 } 39 if(!f) 40 continue; 41 In += 3*Un; 42 bool flag = false; 43 for(int i = 0;i<num;++i) 44 if((prim[i]-In)%6==0 && prim[i] >= In) { 45 flag = true; 46 break; 47 } 48 printf(flag? "Yes ":"No "); 49 } 50 return 0; 51 }