給出乙個串sss。
然後n
nn對li,
ri
l_i,r_i
li,ri
,表示s[l
i,ri
]s[l_i,r_i]
s[li,
ri]
這個子串(下標從1開始)。
對於一組子串,玩兩種遊戲。兩種遊戲操作相同,就是選乙個串,在他後面加上乙個字元使他仍舊是s
ss的子串。
第一種遊戲最後不能操作的人輸,第二種遊戲最後不能操作的人贏。
對於每個i≤n
i\le n
i≤n,求前i
ii個子串做兩個遊戲,分別是先手勝還是後手勝。
首先把sam建出來。發現問題變為了:在乙個dag上,從某個節點出發,走到不能再走為止,不能走的人贏/輸。
顯然使用sg函式,在sam上dp。"不能走的輸"套上nim遊戲結論,"不能走的贏"套上反nim遊戲結論,問題就解決了。虛假。根據現在已經可以公開的情報,anti-nim遊戲並不是總是適用於anti-sg問題。搜尋「anti-sg」便可以找到反例。
至於如何快速找到乙個子串所在的節點,可以在parent樹上倍增,找到深度最深的maxlen大於等於子串長度的節點,就是子串所在節點,一次詢問o
(log∣
s∣
)o(\log |s|)
o(log∣s∣
)。倍增的操作我比賽的時候並沒有想到,可以說我是菜的不行了。
#include
using
namespace std;
const
int n =
1e6+
10, m =
5e5+
10, e =25;
namespace sam
void
copy
(int x,
int y)
fa[y][0
]= fa[x][0
];}int
insert
(char c)
if(p ==
0) fa[np][0
]=1;
else}}
return np;}}
using
namespace sam;
string s;
int sn, n, q[m][2
], dp[pn]
, pos[n]
;bool tmp[s+1]
;int ton[n]
, id[pn]
;void
fake_sort()
void
get_dp_and_fa()
for(
int j =
0; j <= s;
++ j)
if(tmp[j]==0
)}for(
int ii =
1; ii <= cnt;
++ ii)
}int
get_u
(int u,
int _len)
void
solve1()
}int
main()
猴子與香蕉
題目描述 一組研究人員正在設計乙個測試猴子iq的實驗。他們把香蕉吊在屋頂上,同時給猴子提供了磚塊。如果猴子夠聰明,它會把磚塊乙個個疊起來做成乙個塔,然後爬上去拿到自己喜愛的食物。研究人員有n種不同的磚塊,而且每種磚塊都是取之不盡的。每種磚塊都是長方體,第i種磚塊的大小是 xi,yi,zi 磚塊能夠翻...
猴子摘香蕉
房內有乙個猴子,乙個箱子,天花板掛了一串香蕉,其位置如圖所示。猴子為了拿到香蕉,它必須把箱子搬到香蕉下面,然後再爬到箱子上。請定義必要的謂詞,列出問題的初始化狀態 即下圖所示狀態 目標狀態 猴子拿到了香蕉,站在箱子上,箱子位於位置b 1 定義描述環境狀態的謂詞 at x,y x在y處 x y hol...
猴子分香蕉
5只猴子是好朋友,在海邊的椰子樹上睡著了。這期間,有商船把一大堆香蕉忘記在沙灘上離去。第1只猴子醒來,把香蕉均分成5堆,還剩下1個,就吃掉並把自己的乙份藏起來繼續睡覺。第2只猴子醒來,重新把香蕉均分成5堆,還剩下2個,就吃掉並把自己的乙份藏起來繼續睡覺。第3只猴子醒來,重新把香蕉均分成5堆,還剩下3...