2023牛客暑期多校-J-Qu‘est-ce Que C‘est?(DP)

题意:

给定长度为n的数列,要求每个数都在的范围,且任意长度大于等于2的区间和都大于等于0,问方案数。

思路:

首先要看出是dp题,用来表示遍历到第i位且后缀和最小为x 的可行方案数(此时的后缀可以只有最后一位)。很显然j的值在区间。下面考虑dp如何转换:

1.对于。 先讨论可由加一位值为 转换而来;也可由加一位值为0 转换而来。就有。再讨论,可由,加一位值为 转换而来;也可由 加一位值为1转换而来。就有。依次讨论可以得出可以由,末位加值为转换而来;也可由,末位加x转换而来。综上所诉:

2.对于,末位加值为x 才能转换成。所以

为了方便计算我们把这个区间平移映射到区间上。按照上述思想去找新的dp转换式就有:

由于都是求和到2m,所以可以考虑后缀和优化。

代码:

复制代码
//#define _CRT_SECURE_NO_WARNINGS 
//#include<iostream>
//#include<algorithm>
//#include<cstdio>
//#include<map>
//#include<string.h>
//#include<string>
//#include<vector>
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 998244353;
const int N = 5005;
ll dp[N][N*2];//dp[i][j]表示遍历到i位,后缀和最小为j且合法的数量。(这里后缀和包含了只含有最后一位的情况)
ll sum[N * 2];//后缀数组
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n, m;
	cin >> n >> m;
	ll ans = 0;
	//初始化
	for (int i = 0; i <= m*2; i++)
	{
		dp[1][i] = 1;
	}
	for (int i = 2; i <= n; i++)
	{
		//处理后缀和
		for (int j = m * 2; j >= 0; j--)sum[j] = (sum[j + 1] + dp[i - 1][j]) % mod;
		//[0,m)的情况
		for (int j = 0; j < m; j++)
		{
			dp[i][j] = sum[2 * m - j];
		}
		//[m,2m]的情况
		for (int j = m; j <= 2 * m; j++)
		{
			dp[i][j] = sum[j - m];
		}
	}
	//统计
	for (int i = 0; i <= m * 2; i++)
	{
		ans = (ans + dp[n][i]) % mod;
	}
	cout << ans << endl;
	return 0;
}
相关推荐
x_xbx14 小时前
LeetCode:739. 每日温度
算法·leetcode·职场和发展
不会C语言的男孩14 小时前
C++ Primer Plus 第3章:处理数据
开发语言·c++
RuiZN15 小时前
UE5 蓝图 FPS 02 Event Beginplay
c++·ue5
欧米欧15 小时前
C++进阶之AVL树
java·服务器·c++
艾莉丝努力练剑15 小时前
【Linux:文件】库的制作与原理进阶
linux·运维·服务器·网络·数据库·c++·人工智能
计算机安禾15 小时前
【算法分析与设计】第20篇:图论中的NP困难问题与近似策略
大数据·人工智能·算法
Trouvaille ~15 小时前
【优选算法篇】深入浅出链表算法:交换、重排与合并的终极策略
c++·算法·链表·面试·蓝桥杯·笔试·后端开发
Z_Wonderful15 小时前
大文件上传-分片上传-秒传
算法·哈希算法
heimeiyingwang15 小时前
【架构实战】分布式ID生成方案:雪花算法与业务ID设计
分布式·算法·架构
RuiZN15 小时前
UE5 蓝图 FPS 01 Event Tick
c++·ue5