• CF1152 F. Neko Rules the Catniverse (dp)


    题意

    一条长为 (n) 的数轴,可以从任意整点 (in [1, n]) 出发,假设当前在 (x) ,下一步能到达的点 (y) 需要满足,(y) 从未到过,且 (1 le y le x + m) ,问长恰好为 (k) 的合法路径条数。

    数据范围

    对于 (F1)(1 le n le 10^5, 1 le k le min(n, 12), 1 le m le 4)

    对于 (F2​)(1 le n le 10^9​)

    题解

    比较 ( ext{tricky}) 的一个题。

    考虑我们当前假设经过的路径为 (v_1, v_2, cdots, v_p) ,我们当前可以添加一个 (x < min_{i = 1}^{p} {v_i}) 。显然我们是一定可以添加到队尾的,其次我们可以添加到那些 (v_i le x + m) 的前面。

    那么我们就得到一个很显然的 (dp) 了,考虑从大到小依次考虑每个数填还是不填就能轻松转移了。

    具体来说设 (dp[i][j][sta]) 为当前在第 (i) 个位置,路径长度为 (j) ,最后 (m) 个位置状压后的状态为 (sta)

    每次转移的时候,如果不填直接转过去,填的话可以转到后 (m) 个有 (1) 的状态以及队尾,也就是 (1 + bitcount(sta))

    这样 (dp) 刚好每条路都能一一对应上。

    对于 (F1) 直接 (mathcal O(nk2^m)) 就行了,(F2) 考虑利用矩阵快速幂优化到 (mathcal O((k2^m)^3 log n)) 。(说实话 (F2) 没啥意思。。)

    代码

    #include <bits/stdc++.h>
    
    #define For(i, l, r) for (register int i = (l), i##end = (int)(r); i <= i##end; ++i)
    #define Fordown(i, r, l) for (register int i = (r), i##end = (int)(l); i >= i##end; --i)
    #define Rep(i, r) for (register int i = (0), i##end = (int)(r); i < i##end; ++i)
    #define Set(a, v) memset(a, v, sizeof(a))
    #define Cpy(a, b) memcpy(a, b, sizeof(a))
    #define debug(x) cout << #x << ": " << (x) << endl
    
    using namespace std;
    
    template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
    template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }
    
    inline int read() {
    	int x(0), sgn(1); char ch(getchar());
    	for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
    	for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
    	return x * sgn;
    }
    
    void File() {
    #ifdef zjp_shadow
    	freopen ("F1.in", "r", stdin);
    	freopen ("F1.out", "w", stdout);
    #endif
    }
    
    const int N = 1e5 + 1e3, K = 14, M = 4, Mod = 1e9 + 7;
    
    int dp[N][K][1 << M];
    
    int main() {
    
    	File();
    
    	int n = read(), k = read(), m = read();
    
    	dp[0][0][0] = 1;
    	Rep (i, n) For (j, 0, k) Rep (sta, 1 << m) {
    		(dp[i + 1][j][sta >> 1] += dp[i][j][sta])%= Mod;
    		int res = dp[i][j][sta] * (1ll + __builtin_popcount(sta)) % Mod;
    		(dp[i + 1][j + 1][(sta >> 1) | (1 << m - 1)] += res) %= Mod;
    	}
    
    	int ans = 0;
    	Rep (sta, 1 << m)
    		(ans += dp[n][k][sta]) %= Mod;
    	printf ("%d
    ", ans);
    
    	return 0;
    
    }
    
  • 相关阅读:
    AutoCAD 2012安装错误,与.net framework (1603错误)以及ms2005vc++的问题。
    [转载]Thrift的C#入门Demo_图文详解版
    ASPX的Timer位置没放正确,导致整页刷新,而不是UpdatePanel里的内容刷新。
    div、ul、li等无法居中问题,text-align无效 margin auto无效
    flash导入图片缩放后出现毛边、失真、锯齿、文字模糊不清晰的情况
    table居中方法之一:设置width,然后为style设置margin:auto
    ZR普转提day1
    从“四人过桥”到“N人过桥”
    Luogu P2375 [NOI2014]动物园
    Luogu P3435 [POI2006]OKR-Periods of Words
  • 原文地址:https://www.cnblogs.com/zjp-shadow/p/10777887.html
Copyright © 2020-2023  润新知