20200615题解:继续扮演

题目

继续扮演(continue)

【题目描述】

给定两个长度为n的非负整数序列,分别记为\(a_0,a_1,…,a_(n-1)\)\(b_0,b_1,…,b_(n-1)\)。定义b序列的k变换为,把b序列变换成\(b_(k mod n),b_((k+1) mod n),…,b_((k+n-1) mod n)\)
请你求出哪些0≤k≤n-1的k变换得到的b序列满足:存在一个多项式\(P(x)=c_m x^m+c_(m-1) x^(m-1)+⋯+c_1 x+c_0\),使得对于任意\(0≤i≤n-1\)均满足\(P(i)≡a_i-b_i (mod 998244353)\)

【输入数据】

第一行两个整数n和m,表示序列的长度和多项式\(P(x)\)的度数。
第二行n个非负整数,表示\(a_0,a_1,…,a_(n-1)\)
第三行n个非负整数,表示\(b_0,b_1,…,b_(n-1)\)

【输出数据】

第一行一个非负整数cnt,表示满足条件的k的数量。
接下来cnt行每行一个0≤k≤n-1的k,按照升序输出所有满足条件的k。

【数据范围】

Subtask 1 (7pts):\(n-1≤m\)
Subtask 2 (13pts):\(n≤10\) \(m≤10\)
Subtask 3 (29pts):\(n≤100\) \(m≤100\)
Subtask 4 (5pts):\(m=0\)
Subtask 5 (11pts):\(m≤1\)
Subtask 6 (17pts):\(m≤100\)
Subtask 7 (18pts):无特殊限制。
对于全部数据:\(1≤n≤10^5\) \(0≤m≤10^9\) \(0≤a_i,b_i<998244353\)

题解

定义 对于两个长度为n的序列a和b,\(a\sim b\)等价于a和b符合题意,也等价于:由n个点 \((i, a[i]-b[i]),i\in[1,n]\) 可以生成一个m次多项式。

\(n\le m+1\)

\(a\sim b\) 是一定的。所以这道题的 \(m \le 10^9\) 就是吓人的,实际上m与n同阶,都是\(10^5\)

\(n=m+2\) 时:

性质 \(a \sim b\ \and\ b \sim c \Rightarrow a \sim c\)

证明 由n个点\((i,a[i]-b[i])\)可以生成的多项式记为\(f(x)\),由n个点\((i,b[i]-c[i])\)可以生成的多项式记为\(g(x)\),则由n个点\((i,a[i]-c[i])\)\((i,(a[i]-b[i])+(b[i]-c[i]))\)生成的函数就是\(f(x)+g(x)\)。证毕。

所以,可以构造一个序列c使得\(a\sim c\),构造一个序列d使得\(b\sim d\),而\(c\sim d\)的真假很好判定,这样来判定\(a\sim b\)的真假。

\[a:\{a_0, a_1, a_2, \cdots,a_m,a_{m+1}\}\\ c:\{0,0,0,\cdots,0,c_{m+1}\} \]

所以

\[a_i-c_i= \begin{cases} a_i,& \quad i \le m\\ a_i-c_i,& \quad i =m+1 \end{cases} \]

\(a_0\)~\(a_m\)构造出一个\(P(x)\),(拉格朗日插值[难题1]),只需使\(c_{m+1}\)满足\(P(m+1)=a_{m+1}-c_{m+1}\)

\[\therefore c_{m+1} = a_{m+1} - P(m+1). \]

故序列a只有一个唯一的特征值\(c_{m+1}\),记之为\(f(a)\)\(f(b)=d_{m+1}\)同理。

当序列c和d相遇时,由于前m+1个数都是0,所以它们的函数为\(P(x)=0\)\(\therefore c\sim d\Leftrightarrow c_{m+1}=d_{m+1}\)

综上,\(a\sim b\Leftrightarrow f(a)=f(b)\)。 当然,a,b都只能是长度为m+2的序列。

\(n > m+2\) 时:

\(\{a_i,a_{i+1},\cdots,a_j\}\)\(a[i,j]\)

性质

\[(a[0,m+1]\sim b[0,m+1])\and(a[1,m+2] \sim b[1, m+2])\Leftrightarrow(a[0,m+2]\sim b[0,m+2]) \]

证明

\((a-b)[0,m+2]\)可以形成函数时,其长度为m+2的前后缀肯定也可以。所以后者\(\Rightarrow\)前者。

\((a-b)[0,m+1]\)中,\((a-b)[0,m+1]\)的形成的多项式肯定与\((a-b)[1,m+1]\)形成的相同。

\((a-b)[1,m+2]\)中,\((a-b)[1,m+2]\)的形成的多项式肯定与\((a-b)[1,m+1]\)形成的相同。

所以\((a-b)[0,m+1]\)\((a-b)[1,m+2]\)的就会相同。就拿这个函数肯定可以过\((a-b)[0,m+2]\)的所有点。所以前者\(\Rightarrow\)后者。证毕。

性质

\[当l \ge m+1时,\\(a[i,i+l]\sim b[i,i+l])\and (a[i+1,i+l+1] \sim b[i+1, b+l+1])\Leftrightarrow (a[i, i + 1 + l] \sim b[i,i + 1 + l]) \]

证明

后者\(\Rightarrow\)前者略。

因为两对相似的子串的交集长度\(\ge m+1\),所以可以形成唯一的函数。所以这两对相似的子串所形成的函数相同。这个函数就可以作为证明序列相似所需的函数。所以前者\(\Rightarrow\)后者。证毕。

综合上面两个性质(实际上第一个性质就是第二个性质的特殊情况),就可以得到:

要证\(a \sim b\),即证\(\forall i \in [0,n-m-2], f(a[i, i + m + 1] \sim f(b[i,i + m + 1]))\)

设一映射\(g(i)=f(a[i,i+m+1]),i\in [0,n-m-2]\),则\(\bigwedge_{i=0}^{n-m-2}g_a(i)=g_b(i)\Leftrightarrow a\sim b\)

大功告成?不,还有一个循环位移的问题没有解决。

显然,一个m+2长的序列a的\(f(a[0,m+1])\)只与a本身有关。当k=1时,所有的\(a_i\)都到了\(a_{i-1}\),则所有的\(g_a(i)\)都会移动到\(g_a(i-1)\)。也就是说,\(g_a()\)\(a\)同步位移。记位移k位的序列a为\(^ka[]\),同理记\(^kg_a()\),易得\(^ka[i]=a[(i+k)\%n],\ ^kg_a(i)=g_a((i+k)\% n)\)

\[\therefore \ ^ka \sim b \Leftrightarrow \bigwedge_{i=0}^{n-m-2} \ ^kg_a(i)=g_b(i) \Leftrightarrow \bigwedge_{i=0}^{n-m-2}g_a((i+k)\%n)=g_b(i) \]

这显然就是个字符串匹配问题。若字符串\(g_b[0,n-m-2]\)\(g_a\)的k处得配,则说明\(^k a \sim b\)。序列\(a\)需要倍增,这样才能求出\(g_a[0,n)\),而且\(g_a\)求完之后也要倍增。

还有一个[难题1]

如何快速得出\(P(m+1)\)?(\(P(x)\)\(a[0,m]\)构造出的函数)

根据拉格朗日插值,

\[P(x)=\sum_{i=0}^{m}a_i \frac{\prod_{j\in[0,i)\cup(i,m]}(x-j)}{\prod_{j\in[0,i)\cup(i,m]}(i-j)} \]

代入x=m+1就是:

\[P(m+1)=\sum_{i=0}^{m}a_i \frac{\prod_{j\in[0,i)\cup(i,m]}(m+1-j)}{\prod_{j\in[0,i)\cup(i,m]}(i-j)} \]

\(h(i)=\frac{\prod_{j\in[0,i)\cup(i,m]}(m+1-j)}{\prod_{j\in[0,i)\cup(i,m]}(i-j)}\)。分子、分母分别可以用两个阶乘来表示,可以\(O(1)\)算。\(O(N)\)可以求完所有的\(h(i)\)

然后有

\[P(m+1)=\sum_{i=0}^m a_i h(i) \]

可以用FFT做。

FFT做法:

\(a_i\)不需要多考虑。令多项式\(F(x)=\sum_{i=0}^m a_i x^i\)

\(h(i)\)反个向,令\(G(x)=\sum_{i=0}^m h(m-i)x^i\)

\[(F * G)(x) = \sum_{i=0}^m \sum_{j=0}^ia[j]h(m-(i-j))x^i \]

\(\therefore (F*G)_m = \sum_{j=0}^m a[j]h(m-m+j))\)就是需要的答案。时间\(O(m \log m)\)

但是,就算是这样,求出a的所有n个\(g_a()\)也需要\(O(nm \log m)\)啊。但是很明显这是可以优化的,因为相邻的两个\(g_a(i)=f(a[i,i+m+1])\)所对应的a序列有着很大的重叠部分。

如果令\(F(x)=\sum_{i=0}^n a_i x^i\)(上界由m换成了n),则可以一次FFT得到所有长度为m+2的a的子段的\(P(m+1)\)。设由\(a[i,i+m+1]\)得到的函数为\(P_i(x)\)(但是每一个点的横坐标仍然按照0到m+1算),则有\(g_a(i) =f(a[i,i+m+1])=a_{i+m+1} - P_i(m+1)\)。要求的就是所有\(P_i(m+1)=\sum_{j=0}^m a_{i+j}h(j)\)

\[P_i(m+1)=(F*G)_{m+i}=\sum_{j=i}^{m+i}a[j]h(j-i)=\sum_{j=0}^ma[j+i]h(j) \]

所以

\[g_a(i)= a_{i+m+1} - (F*G)_{m+i},\quad i\in[0,n) \]

\(g_b()\)实际上只需要求出\(g_b(0)\)\(g_b(n-m-2)\),但是为了代码好写,干脆\([0,n)\)都求出来得了。

posted @ 2020-06-15 22:06  lightmain  阅读(154)  评论(0编辑  收藏  举报