TZOJ--1518: 星星点点 (二进制模拟)

1518: 星星点点 

时间限制(普通/Java):1000MS/10000MS     内存限制:65536KByte

描述

输入一个由“*”和“.”组成的字符串,然后根据规则生成下一行字符串: 
如果该行的第i和第i+1个位置上的符号不同,则下一行的第i个位置上为“*”,否则为“.”,其最后一个位置的字符由上一行的第一个和最后一个字符决定。反复应用上述规则足够多次后,某行的字符排列可能在以后的行中再次出现,或者不会再次出现。找出最近的相同的两行之间相差的行数。

输入

上述字符串,长度2<=L<=30。

输出

相差的行数(即行号相减)。

样例输入

.*.
***.

样例输出

3
1

题目来源

ZJGSU

 

题目链接:tzcoder.cn/acmhome/problemdetail.do?&method=showdetail&id=1518

模拟题,按照题目意思模拟,将每一个出现的字符串存入map中,判断是否出现重复的,但用字符串模拟会TLE,题目中只有两种字符,所以转换成二进制进行模拟,根据题目要求提取出转换式子y=(((y&1)<<(n-1))|(y>>1))^y;。

 

#include <string>
#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	string s;
	map<int,int>m;
	while(cin>>s)
	{
		int k=0,n=s.length(),y=0;
		for(int i=0;i<n;i++){
			if(s[i]=='*')y|=(1<<i);
		}
		//cout<<y<<" ";
		m.clear();
		while(1)
		{
			k++;
			if(m[y])break;
			m[y]=k;
			y=(((y&1)<<(n-1))|(y>>1))^y;
			//cout<<y<<endl;
		}
		//mp[s]=k-m[s];
		cout<<k-m[y]<<endl;
	}
}

 

 

原文地址:https://www.cnblogs.com/Anidlebrain/p/10028978.html