题解:CF2092D Mishkin Energizer

不难发现形如 LIT 的串是万能的。证明如下:

  • 可以多生成一个 L 变为 LILT
  • 可以多生成一个 T 变为 LTIT
  • 想要多生成一个 I,先选择上面两个的其中一个操作,然后同理即可。

进一步地,只要存在相邻两个字母不同,就可以花费一个操作变为万能串。每一步最多操作两次即可向着目标前进,故总次数不会超过 2n2n2n

由于还需要记录路径,当 LIT 变为 ILT 后,需要注意万能串最左侧的位置会增加 111。直接用 while 配套着 swap 需求的写法最为简洁。

#include <bits/stdc++.h>
#define init(x) memset (x,0,sizeof (x))
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define pii pair <int,int>
using namespace std;
const int MAX = 105;
const int MOD = 1e9 + 7;
inline int read ();
int t,n,tot,ok,cnt[200];char s[MAX];
vector <int> ans;
int main ()
{
	//freopen (".in","r",stdin);
	//freopen (".out","w",stdout);
	tot = 'L' ^ 'I' ^ 'T';
	t = read ();
	while (t--)
	{
		n = read ();scanf ("%s",s + 1);
		ok = cnt['L'] = cnt['I'] = cnt['T'] = 0;
		ans.clear ();
		for (int i = 1;i <= n;++i)
		{
			if (i > 1 && s[i] != s[i - 1]) ok = 1;
			++cnt[s[i]];
		}
		if (!ok) {puts ("-1");continue;} //无法构造出万能串,肯定是无解
		if (cnt['L'] == cnt['I'] && cnt['I'] == cnt['T']) {puts ("0");continue;}//无需操作就直接特判
		for (int i = 2;i <= n;++i)
		{
			if (s[i] == s[i - 1]) continue;
//由 AB -> ACB 构造万能串
			int x = s[i - 1],z = s[i],y = tot ^ (x ^ z),p = i - 1;
			ans.push_back (p);++cnt[y];
			while (cnt[x] != cnt[y] || cnt[x] != cnt[z] || cnt[y] != cnt[z])
			{
				if (cnt[x] > cnt[z]) ans.push_back (p),++cnt[z],swap (y,z);
				else ans.push_back (++p),++cnt[x],swap (x,y);//万能串最左侧的位置右移
			}
			break;	
		}
		printf ("%d\n",ans.size ());
		for (auto v : ans) printf ("%d\n",v);
	}
	return 0;
}
inline int read ()
{
    int s = 0;int f = 1;
    char ch = getchar ();
    while ((ch < '0' || ch > '9') && ch != EOF)
	{
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9')
	{
        s = s * 10 + ch - '0';
        ch = getchar ();
    }
    return s * f;
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值