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_0\)~\(a_m\)构造出一个\(P(x)\),(拉格朗日插值[难题1]),只需使\(c_{m+1}\)满足\(P(m+1)=a_{m+1}-c_{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-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\)后者。证毕。
性质
证明
后者\(\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)\)。
这显然就是个字符串匹配问题。若字符串\(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]\)构造出的函数)
根据拉格朗日插值,
代入x=m+1就是:
设\(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)\)。
然后有
可以用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\)。
\(\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)\)。
则
所以
\(g_b()\)实际上只需要求出\(g_b(0)\)到\(g_b(n-m-2)\),但是为了代码好写,干脆\([0,n)\)都求出来得了。