結論題,假設那個串叫ss,並且操作一次後變成tt。
首先自己畫畫就會發現t比s多出來的那一段一定是s的乙個週期。(注意s的週期和ss的週期不是一回事,比如樣例)
字首技能:如果a和b都是s的週期,那麼(a, b)也是s的週期。因此s的最小正週期是s的任何乙個週期的週期,證明類似輾轉相除。
然後我們證明對於任意情況下,你選擇的週期,記做g,越小越好,也就是選擇最小週期g。否則,假設選擇的是h是s的乙個週期並且做出來的結果比g好。那麼根據一些border的知識我們知道因為g是最小正週期所以h的長度是g的長度我的若干倍,那麼顯然h能做到的事情g也能做到。因此h不會比g好。
否則,我們證明這麼兩件事情:
1)f(ss)=sgsg
這個其實自己畫畫就能畫出來。
2)若s的最小正週期是g,那麼串sg的最小正週期為:
a)g,如果g的長度是s的因數,這顯然。
b)s,else。我們證明b)。
反證。首先s是sg的乙個週期。因此假定h是sg的最小正週期,那麼|h|< |s|,否則結論成立。那麼根據border的知識,s的h的倍數。因此h也是s的乙個週期,從因此g的長度是h的長度的因數,因此g的長度是s的長度的因數,這樣就gg了。
我們考慮上述兩個結論在幹啥,根據1),我們知道就是,考慮這個偶串的前半段會不停的加上乙個最小正週期。
如果g的長度是s的長度的因數,那麼相當與每次在後面加入兩個g,也就是最終序列全是g,自己特判掉就可以了。下文假設g的長度不是s的長度的因數
根據後半段,我們假設操作了x次後這個串的前半部分是sg,s是操作第x-1次串,那麼s是sg的最小正週期,第x+1次操作後的串前半部分就是sgs,也就是每次操作得到的串都是上兩次操作得到的串拼起來,就像乙個斐數一樣。
實現的時候其實不用特判整除的情況。
#include
#include
#include
#include
#define n 200010
#define lint long long
#define debug(x) cerr<<#x<<"="<#define sp <<" "
#define ln namespace
std;
char s[n];int nxt[n];
struct e
inline e operator=(const e &e)
inline e operator+(const e &e)const
inline e operator-(const e &e)const
inline e operator+=(const e &e)
}a[1010];
inline
int getg(char *s,int n)
return n-nxt[n];
}inline e query(lint n,int c)
int main()
ARC077 D 組合數公式 水
題目大意 給你乙個長度為n 1的序列。1到n 1到n1到 n至少會出現一次。對於每個k,k 1,n k,k in 1,n k,k 1 n 問你有多少個本質不同的子串行。題目思路 一定有一對重複的。如 xayyyyyazzzz.那麼同時選擇x和z x和zx和 z區域裡的數,不選y yy區域,且選擇了中...