MU Puzzle(推理找规律)(多校第六场))

 

【题目链接】:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1008&cid=460

 

【解题思路】:

这题初看起来情况很复杂,动态性很高,但注意到一个很特殊的地方,就是他每次都是以MI这个为起点的,只要先从这个往下推,看得出的串有什么规律就行

了。这类题就是推导出数学式子,然后利用数学公式推导出条件。

 

    1)  由MI 往下推可得MII,MIIII,MIIIIIIII……等后跟着2^n个I,而任意位置3个I可组成一个U,如果不消去UU,则以后每次翻倍后,把U换成I,则必然有2^n个I;

    2) 而每次消去两个U,则以后再经翻倍,则少2^n - cur = 6*k,所以判断只要将M后的UI序列中U换成3个I,统计下I的个数,若能满足存在某个n 使2^n减去I的个数是6的倍数,

           就可以判断其为满足条件的串(我刚开始鬼使神差的认为找到离I个数最近且比它大的2^n,潜意识不知道什么时候形成了这样的思维定势,结果wa了良久。这启示我在写代

           码和尤其是检查代码时,不仅要看写的对不对,而且要对每一条语句问为什么是这样写,为什么不是那样写?这样会更好的避免思维定势)

 

    3)设I的个数为x,U的个数为y,得出公式,2^n - (x+3y) = 6k ,则进一步化为2^n = x+3y+6k;我们来将右边构造出2^n,考察右边的式子:

         首先(x+3y)%2==0 满足两边偶数的条件,另外3的倍数是得不到2^n的,所以(x+3y+6k)%3!=0;则 (x+3y)==6n1+2 或 (x+3y)==6n2+4 可以证明这两式都存在k可以满足、

         2^n = x+3y+6k;简单点证明就是:

         a.将上式同除以2,得到(x+3y)/2=3k+1 或(x+3y)/2=3k+2;令m=(x+3y)/2;(因为之前说过(x+3y)必须是偶数,所以m是整数)

        得m=3k+1或m=3k+2;所以只需证明

        所以限制条件即为(x+y)%2==0 && x%3 !=0 ;另外注意下边界情况。

 

   PS:另外这题明显的按两种规则扩展每次I数量*2或减去6,明显的BFS扩展方式,由于数据不大,可一次BFS打表即可,判断时只需计算转化后I的总个数再看表中有无即可。

 

【借用同学的代码】:

#include<iostream>
#include<cstring>
using namespace std;
char str[1000010];
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		cin>>str;
		int l=strlen(str),xi=0,xu=0,k=0;
		if(str[0]!='M')
		{
			cout<<"No"<<endl;
			continue;
		}
		for(int i=1;i<l;i++)
		{
			if(str[i]=='I')
			    xi++;
			else if(str[i]=='U')
			    xu++;
			else
			{
				k=1;
				break;
			}
		}
		if(k==1 || ((xi+xu)%2==1 && !(xi==1 && xu==0)) || xi%3==0)
		{
			cout<<"No"<<endl;
			continue;
		}
		else
		{
			cout<<"Yes"<<endl;
			continue;
		}	
	}
}


 

posted on 2013-08-11 11:21  Gddxz  阅读(237)  评论(0编辑  收藏  举报

导航