1 条题解

  • 0
    @ 2025-8-24 22:30:23

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar LGyxj
    摆烂是一种态度

    搬运于2025-08-24 22:30:23,当前版本为作者最后更新于2023-09-27 16:20:12,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    最开始以为是反演,但很快发现并不是。

    考虑进行 dp 。

    fk,nf_{k, n} 表示走了 kk 步,走到第 nn 个点。

    不难想出,有以下转移:

    fk,n=x=1mfk1,nxf_{k, n} = \sum\limits_{x = 1}^m f_{k - 1, n - x}

    于是写出它的生成函数

    g=i=1mxig = \sum\limits_{i = 1}^m x^i fk=gkf_k = g^k

    那么我们要求的就是

    hk=i=0kfih_k = \sum\limits_{i = 0}^k f_i

    显然,这个东西是可以倍增的,即

    h2k=hk+fkhkh_{2k} = h_k + f_k * h_k

    那么求出所有 h2ih_{2^i}f2if_{2^i},这部分是 O(nlogk)O(n \log k) 的。

    再对 kk 进行二进制数位 dp 即可,不难发现,这部分也是 O(nlogk)O(n \log k) 的。

    主要代码如下

    void solve() {
    	for (int i = 0; i < Nn; ++ i) cur[i] = 1;
    	for (int i = 1; i <= m; ++ i) g[i] = 1;
    	fft(g); memcpy(f[0], g, sizeof g);
    	memcpy(h[0], g, sizeof g);
    	for (int i = 1; i < 14; ++ i) {
    		for (int j = 0; j < Nn; ++ j) 
    			f[i][j] = 1ll * f[i - 1][j] * f[i - 1][j] % mod;
    		for (int j = 0; j < Nn; ++ j) 
    			h[i][j] = (h[i - 1][j] + 1ll * h[i - 1][j] * f[i - 1][j]) % mod;
    	}
    	for (int i = 14; ~i; -- i) {
    		if (k >> i & 1) {
    			for (int j = 0; j < Nn; ++ j) 
    				qx[j] = (qx[j] + 1ll * cur[j] * h[i][j]) % mod;
    			for (int j = 0; j < Nn; ++ j) cur[j] = 1ll * cur[j] * f[i][j] % mod;
    		}
    	}
    	fft(qx, 0); qx[0] = 1;
    }
    
    • 1

    信息

    ID
    6603
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者