[POI2009]Slw

题目

神题!!只有(POI)出得出来的神题!!

只能说好像懂了,不想听蒟蒻废话就右转(dalao)博客

目前网上除官方外仅三篇题解,由于推论无法直观得出且有点复杂,难免不好理解,手玩数据最重要

做法

由于都是以(H^x(0))开始,一下简写成(H^x)
性质:
(~~~~~1.)斐波那契堆:(H^x=H^{x-1}+H^{x-2})(0longrightarrow 1longrightarrow 10longrightarrow 101longrightarrow 10110)

(~~~~~2.)(x)为偶数时(0)结尾,为奇数时(1)结尾

(~~~~~3.)定义(G^-1)(H^1)的逆操作,则(s_1)(s_2)的子串时,逆操作也有此性质

(~~~~~4.)出现(00)一定不合法

(~~~~~5.)出现(111)时则一定不合法,把这个子串化成一般形式为(10101+0)

(~~~~~6.)(x≥5)(x)为奇数时有后缀(10101),也就是说(x≥5)(x+1=0)时一定不合法

神奇的推导:
(~~~~~)我们把所有的(x),写成序列({a_1,a_2...a_{n-1},a_n})的形式

(~~~~~)(forall vin {a_1,a_2...a_{n-1},a_n}>0)时我们可以集体减(1)

(~~~~~)所以考虑(0)的特殊情况:

(~~~~~)前面为偶数一定不合法(性质(2)),考虑奇数:((1:10),合并转换为(2))((3:1010),转换为两个(2))

(~~~~~)剩下的都不合法了

特殊情况:
(~~~~~)由于性质(4)三子串的出现我们不好判断,而且两个(1)转换后不合法但是实际是合法的

(~~~~~)(11)出现在中间后面只能接(0),这种情况会合并的,(11+x)按之前的方法会判非法

(~~~~~)仅考虑在后面的情况,我们是可以直接去掉最后的(1)的,而(111)这种非法情况去掉后依然会判非法不用管了

(~~~~~)相似的,末尾(3)也会出现这种特殊情况改为(2)

My complete code

代码(copy)来的

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n;
int a[M];
bool Solve(){
	int i;
	while(n>1){
		if(!a[1]) a[1]=2;
		if(a[n]==1) n--;
		else if(a[n]==3) a[n]=2;
		for(i=n;i;i--)
			if(!a[i]){
				if(a[i-1]==1)
					a[i-1]=2,a[i]=-1;
				else if(a[i-1]==3)
					a[i-1]=2,a[i]=2;
				else
					return false;
			}
		int temp=0;
		for(i=1;i<=n;i++)
			if(a[i]!=-1)
				a[++temp]=a[i];
		n=temp;
		for(i=1;i<=n;i++)
			a[i]--;
	}
	return true;
}
int main(){
	int T,i;
	for(cin>>T;T;T--){
		cin>>n;
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		puts(Solve()?"TAK":"NIE");
	}
	return 0;
}

原文地址:https://www.cnblogs.com/y2823774827y/p/10492032.html