20200615题解:继续扮演
Posted lightmain-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,(asim b)等价于a和b符合题意,也等价于:由n个点 ((i, a[i]-b[i]),iin[1,n]) 可以生成一个m次多项式。
当 (nle m+1) 时
(asim 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使得(asim c),构造一个序列d使得(bsim d),而(csim d)的真假很好判定,这样来判定(asim 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)。( herefore csim dLeftrightarrow c_{m+1}=d_{m+1})。
综上,(asim bLeftrightarrow 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]),iin [0,n-m-2]),则(igwedge_{i=0}^{n-m-2}g_a(i)=g_b(i)Leftrightarrow asim 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_{jin[0,i)cup(i,m]}(m+1-j)}{prod_{jin[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)。
( herefore (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))都求出来得了。
以上是关于20200615题解:继续扮演的主要内容,如果未能解决你的问题,请参考以下文章