zoukankan      html  css  js  c++  java
  • 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:{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= egin{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})

    [ herefore 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)( 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[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]),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))

    [ herefore ^ka sim b Leftrightarrow igwedge_{i=0}^{n-m-2} ^kg_a(i)=g_b(i) Leftrightarrow igwedge_{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_{jin[0,i)cup(i,m]}(x-j)}{prod_{jin[0,i)cup(i,m]}(i-j)} ]

    代入x=m+1就是:

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

    (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))

    然后有

    [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 ]

    ( 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))

    [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 iin[0,n) ]

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

  • 相关阅读:
    在Arduino IDE中安装ESP32 Filesystem Uploader
    人工智能必备数学基础:线性代数基础(1)
    人工智能必备数学基础:高等数学基础(3)
    迟到的=2020=年终总结
    常用软件-官方下载地址
    海康、大华的RTSP地址规则说明及通道问题(重点)
    各类服务器性能的瓶颈分析
    分析影响流媒体服务器性能的硬件瓶颈
    linux下程序、动态库、静态库内部添加版本号和编译时间与Windows下Qt 如何给程序添加版本信息
    css link import 两者之间的区别
  • 原文地址:https://www.cnblogs.com/lightmain-blog/p/13138163.html
Copyright © 2011-2022 走看看