洛谷P4933 大师

文章讲述了洛谷上的一道编程题目,涉及等差数列的概念。题目要求找出所有使剩余电塔高度形成等差数列的方案数,通过动态规划方法优化时间复杂度,达到O(n^3),并提供了代码实现。答案需要对998244353取模。
摘要由CSDN通过智能技术生成

洛谷P4933 大师

题意

建筑大师最近在跟着数学大师 ljt12138 学数学,今天他学了等差数列,ljt12138 决定给他留一道练习题。

ljt12138 首先建了 n n n 个特斯拉电磁塔,这些电塔排成一排,从左到右依次标号为 1 1 1 n n n,第 i i i 个电塔的高度为 h [ i ] h[i] h[i]

建筑大师需要从中选出一些电塔,然后这些电塔就会缩到地下去。这时候,如果留在地上的电塔的高度,从左向右构成了一个等差数列,那么这个选择方案就会被认为是美观的。

建筑大师需要求出,一共有多少种美观的选择方案,答案模 998244353 998244353 998244353

注意,如果地上只留了一个或者两个电塔,那么这种方案也是美观的。地上没有电塔的方案被认为是不美观的。

同时也要注意,等差数列的公差也可以为负数。

v v v 为最高的电塔高度。

对于前 30 % 30\% 30% 的数据, n ≤ 20 n \le 20 n20

对于前 60 % 60\% 60% 的数据, n ≤ 100 n \le 100 n100 v ≤ 2 × 1 0 3 v \le 2 \times 10^3 v2×103

对于另外 20 % 20\% 20% 的数据,所有电塔的高度构成一个等差数列。

对于 100 % 100\% 100% 的数据, n ≤ 1 0 3 n \le 10^3 n103 v ≤ 2 × 1 0 4 v \leq2 \times 10^4 v2×104

思路

判断一个数是否在一个等差数列内可以用数列的首项和公差来求——但是这样的时间复杂度是 O ( n 2 v ) O(n^2v) O(n2v)的,无法接受——如何确立一种与 v v v无关的状态呢?
我们发现,等差数列的公差就等于相邻两项之差,那么我们可以用枚举最后一项和倒数第二项来求!此时时间复杂度为 O ( n 3 ) O(n^3) O(n3),且实际上跑不到那么大(因为第三项下标小于第二项下标,第二项下标小于第一项下标),可以接受。
根据等差数列的公式 a [ n ] + a [ m ] = 2 a [ m + n 2 ] a[n] + a[m] = 2a[\frac{m+n}2] a[n]+a[m]=2a[2m+n]直接暴力枚举, d p [ x ] [ y ] dp[x][y] dp[x][y]表示以最后一项和倒数第二项为等差数列的数列的数量,而因为直接将,可推出状态转移方程
d p [ i ] [ x ] = ∑ x = 1 i − 1 ∑ y = 1 x − 1 d p [ x ] [ y ] ( a [ y ] + a [ i ] = 2 a [ x ] ) dp[i][x] = \sum_{x=1}^{i-1}\sum_{y=1}^{x-1} dp[x][y](a[y] + a[i] = 2a[x]) dp[i][x]=x=1i1y=1x1dp[x][y](a[y]+a[i]=2a[x])
而答案就是 d p dp dp数组值的总和,顺路加一下即可。最后还有只有一个电塔的情况,直接 a n s + n ans+n ans+n即可。记得取模哦!

代码

#include <iostream>
#define piasticOuO 998244353
using namespace std;
int n, h[1005];
int ans, dp[1005][1005];		//dp[x][y]表示最后一项为h[x] 倒数第二项为h[y]的数列的项数

int main() {

	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> h[i];
		for (int x = 1; x < i; ++x) {
			dp[i][x] = 1;
			ans ++;
			for (int y = 1; y < x; ++y) {
				if (h[y] + h[i] == h[x] * 2) {
					dp[i][x] += dp[x][y];
					ans += dp[x][y];
					dp[i][x] %= piasticOuO;
					ans %= piasticOuO;
				}
			}
		}
	}
	cout << ans + n;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值