zoukankan      html  css  js  c++  java
  • AGC046C Shift

    题面

    题解

    Orz (mathsf{color{black}{c}color{red}{jrzn}})

    考虑将每一种方案记在操作数最少的 dp 值上,可以发现 (k > n) 是没用的。

    (f_{i, j, k}) 表示当前考虑到第 (i) 位,有 (j)(1) 从后面被搬到了前面,操作了 (k) 次的方案数。

    由于从后往前有 (j)(1) 发生移动,所以第 (i) 个位置所对应的字符为 (s_{i - j})

    转移考虑当前的字符和你想填的字符,可以有四种转移:

    (s_{i - j + 1}) 和下一位要填的值相等时,有 (f_{i + 1, j, k} gets f_{i, j, k})

    (s_{i - j + 1} = 0) 且下一位要填 (1) 时,只能从后面搬运一个 (1) 到前面去,于是有 (f_{i + 1, j + 1, k + 1} gets f_{i, j, k})

    (s_{i - j + 1} = 1) 且下一位要填 (0) 时,可以发现这些 (1) 必须要被搬到前面去,记 (mathrm {nxt}_{i, j}) 表示最大的满足 (s_{i - k + 1} = 0)(k),那么下一个位置实际上是匹配的 (mathrm {nxt}_{i, j}) 这个位置,于是有转移 (f_{i + 1, mathrm{nxt}_{i, j}, k} gets f_{i, j, k})

    最后计算答案,发现 (f_{n, i, j}) 如果要满足条件当且仅当 (s_{n - i + 1 cdots n}) 全是 (1) 才能够保证 (1) 的个数是对的,那么加上所有满足条件的 dp 值即可。

    代码

    #include <cstdio>
    #include <cstring>
    
    const int N(305), Mod(998244353);
    inline int upd(const int &x) { return x + (x >> 31 & Mod); }
    inline void Add(int &x, const int &y) { x = upd(x + y - Mod); }
    int n, K, f[N][N][N], nxt[N][N];
    char s[N];
    
    int main()
    {
    	std::scanf("%s%d", s + 1, &K);
    	n = std::strlen(s + 1), f[0][0][0] = 1;
    	for (int i = 0; i < n; i++)
    		for (int j = 0, t; j <= i; j++)
    		{
    			for (t = j; s[i + 1 - t] == '1' && t >= 0; --t);
    			nxt[i][j] = t;
    		}
    	if (K > n) K = n;
    	for (int i = 0; i < n; i++)
    		for (int j = i; j >= 0; j--)
    			for (int k = 0; k <= K; k++)
    				if (s[i + 1 - j] == '0')
    				{
    					Add(f[i + 1][j][k], f[i][j][k]);
    					Add(f[i + 1][j + 1][k + 1], f[i][j][k]);
    				}
    				else
    				{
    					Add(f[i + 1][j][k], f[i][j][k]);
    					if (~nxt[i][j]) Add(f[i + 1][nxt[i][j]][k], f[i][j][k]);
    				}
    	int ans = 0;
    	for (int i = 0; i <= n; i++)
    	{
    		int c = 0;
    		for (int j = n - i + 1; j <= n; j++) c += s[j] - '0';
    		if (c == i) for (int j = 0; j <= K; j++) Add(ans, f[n][i][j]);
    	}
    	std::printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    c++设计模式:工厂模式(Factory Pattern)
    lua和tolua++的安装
    c++设计模式:观察者模式(Observer Pattern)
    c++设计模式:抽象工厂模式(Abstract Factory Pattern)
    linux下搭建eclipsec++开发环境
    c++设计模式:单件模式(Singleton Pattern)
    SQL SERVER查询Job每个步骤执行结果情况
    XMLA清空Cube缓存
    【转载】SSIS 包组件的命名规则
    SQL SERVER 游标删除无数据试图
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/14033167.html
Copyright © 2011-2022 走看看