HDU 4662 MU Puzzle

MU Puzzle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 299    Accepted Submission(s): 157

Problem Description
Suppose there are the symbols M, I, and U which can be combined to produce strings of symbols called "words". We start with one word MI, and transform it to get a new word. In each step, we can use one of the following transformation rules:
1. Double any string after the M (that is, change Mx, to Mxx). For example: MIU to MIUIU.
2. Replace any III with a U. For example: MUIIIU to MUUU.
3. Remove any UU. For example: MUUU to MU.
Using these three rules is it possible to change MI into a given string in a finite number of steps?
 

 

Input
First line, number of strings, n.   Following n lines, each line contains a nonempty string which consists only of letters 'M', 'I' and 'U'.  
Total length of all strings <= 10 6.
 

 

Output
n lines, each line is 'Yes' or 'No'.
 

 

Sample Input
2
MI
MU
 

 

Sample Output
Yes
No
 

 

Source
 

 多校第六场也结束了,我们队每场都只能过一两道题,感觉前途渺茫啊……

第六场的1008,这场比赛我唯一AC的一道题,也是我们队唯一AC的一道题

给一个字符串,问它能否由MI按照题干中给的规则转换过来

我的做法是,由规则逆向思考,先所给串中所有的U全部换成3个I,然后统计I的个数。

由第一条规则和第三条规则易知I的个数一定能写成(2^x-6*y)的形式,否则不能由MI转化过来

因此只要判断I的个数和比刚好比它大的两个2^x的差能否被六整除即可。(注意这里一定要判断2个2^x,因为2^x对六的模可能是2或4,交替出现)

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 
 5 using namespace std;
 6 
 7 int len;
 8 int two[50];
 9 char s[1000100];
10 
11 void initial()
12 {
13     two[0]=1;
14     for(int i=1;i<=30;i++)
15         two[i]=two[i-1]*2;
16 }
17 
18 int main()
19 {
20     int t;
21 
22     initial();
23 
24     scanf("%d",&t);
25     getchar();
26 
27     while(t--)
28     {
29         gets(s);
30         if(s[0]!='M')
31         {
32             cout<<"No"<<endl;
33             continue;
34         }
35         int len,ans=0;
36         bool flag=true;
37         len=strlen(s);
38         for(int i=1;i<len&&flag;i++)
39             if(s[i]=='I')
40                 ans++;
41             else if(s[i]=='U')
42                 ans+=3;
43             else if(s[i]=='M')
44             {
45                 cout<<"No"<<endl;
46                 flag=false;
47             }
48         if(!flag)
49             continue;
50         int i;
51         for(i=0;i<=30;i++)
52             if(two[i]>=ans)
53                 break;
54         if((two[i]-ans)%6==0||(two[i+1]-ans)%6==0)
55             cout<<"Yes"<<endl;
56         else
57             cout<<"No"<<endl;
58     }
59 
60     return 0;
61 }
[C++]

 

转载于:https://www.cnblogs.com/lzj-0218/p/3246903.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值