1. 程式人生 > >【JZOJ A組】VanUSee

【JZOJ A組】VanUSee

Description

眾所周知,cqf童鞋對哲學有著深入的理解和認識,並常常將哲學思想應用在實際生活中,例如鍛鍊摔角技術或者研究化(fa)學。
由於cqf童鞋哲學造詣太過高深,以至於影響到了pty,他們常常給在一塊VanUSee。Van的都是一些像“裝備回收交易自由”、“開局一條鯤進化全靠吞”、“今晚八點是兄弟就來肝”這樣高階大氣上檔次的著名USee。
有一天他們決定Van一個親民的USee來和大家分享他們的哲學心路歷程
規則是這樣的:
“給定兩個串S和T,|S| >= |T|。
cqf和pty輪流操作串S,cqf先手。
對於每次操作,cqf或pty會選擇刪掉S的第一位或最後一位。
當操作以後的串的長度等於|T|時,遊戲停止。
如果停止時的串=T,則pty獲勝,否則cqf獲勝。”
cqf和pty的哲學思維都很強,他們都能採取最優的策略來行動
作為高階玩家的蘇巴先生在一旁觀戰,他早已看穿了這個USee的本質,當兩個串給出的那一瞬間勝負已分,然而不是所有圍觀者的水平都像蘇巴先生那麼高,其中也沒有五年級的積分小哥,他們又想知道結果,於是圍觀者們找到了能預見一局圍棋接下來40手的你。

Input

有多組資料
第一行一個正整數t表示資料組數
接下來t組資料,每組資料兩行,接下來總共2t行
第一行一個字串S
第二行一個字串T
字串僅由小寫字元組成

Output

t行,對於每一組資料輸出雙方都是最優策略時誰是贏家(“cqf”或者“pty”,不含引號,小寫)

Sample Input

5
aba
b
bab
b
aaab
ab
xyz
mnk
xyz
xyz

Sample Output

pty
pty
cqf
cqf
pty
樣例解釋:
對於第一組S=“aba”,T=“b”
cqf無論刪掉頭還是尾,pty都可以刪掉另一個來使剩下的是“b”
對於第三組S=“aaab”,T=“ab”
cqf只需第一次刪掉“b”,以後就永遠不能達到“ab”了

Data Constraint

對於30%的資料,1<=|T|<=|S|<=20
對於100%的資料,1<=t<=10 1<=|T|<=|S|<=100000

Hint

這題確實很有趣。

思路

千萬不要被樣例迷惑!!!

當|S|-|T|為奇數時,最後一次操作是先手做,它肯定往不是目標狀態走,那麼一個
位置在最後一次操作前是目標狀態當且僅當它+1 它-1 都是目標狀態
現在就全部轉化成|S|-|T|為偶數的情況
假如 0 是目標狀態,那麼顯然後手會贏,因為無論先手往哪裡走後手都可以把他拉
回來
如果 0 不是,並且-2 和 2 不全是,那麼先手一定會朝不是的那一邊走,後手無論
如何都沒有辦法將它拉回到是的那一邊了
因此後手會贏當且僅當 0 是目標狀態或者-2 和 2 都是目標狀態
否則都是先手贏

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=5e5+77;
int t,l1,l2;
char st1[N],st2[N];
bool check(int x)
{
	for(int i=1; i<=l2; i++)
	{
		if(st1[x+i]!=st2[i]) return 0;
	}
	return 1;
}
int main()
{
	freopen("vanusee.in","r",stdin),freopen("vanusee.out","w",stdout);
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s%s",st1+1,st2+1);
		l1=strlen(st1+1),l2=strlen(st2+1);
		if(l1==l2&&check(l1))
		{
			printf("pty\n"); continue;
		}else
		if((l1-l2)%2==1)
		{
			if(check((l1-l2-1)/2)&&check((l1-l2+1)/2))
			{
				printf("pty\n"); continue;
			}else
			{
				printf("cqf\n"); continue;
			}
		}else
		{
			if(check((l1-l2)/2)||check((l1-l2-2)/2)&&check((l1-l2+2)/2))
			{
				printf("pty\n"); continue;
			}else
			{
				printf("cqf\n"); continue;
			}
		}
	}
}