• 洛谷 P4933 大师


    题目:大师

    网址:https://www.luogu.com.cn/problem/P4933

    题目背景

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

    题目描述

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

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

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

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

    输入格式

    第一行一个正整数n。

    第二行n个非负整数,第i个整数是第i个电塔的高度h[i]。

    输出格式

    输出一个整数,表示美观的方案数模998244353的值。

    输入输出样例
    输入
    8
    13 14 6 20 27 34 34 41 
    
    输出
    50
    
    输入
    100
    90 1004 171 99 1835 108 81 117 141 126 135 144 81 153 193 81 962 162 1493 171 1780 864 297 180 532 1781 189 1059 198 333 1593 824 207 1877 216 270 225 1131 336 1875 362 234 81 288 1550 243 463 1755 252 406 261 270 279 288 1393 261 1263 297 135 333 872 234 881 180 198 81 225 306 180 90 315 81 81 198 252 81 297 1336 1140 1238 81 198 297 661 81 1372 469 1132 81 126 324 333 342 81 351 481 279 1770 1225 549 
    
    输出
    11153
    
    说明/提示

    我们用v表示最高的电塔高度。

    对于前30%的数据,n<=20。

    对于前60%的数据,n<=100,v<=2000。

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

    对于100%的数据,n<=1000,v<=20000。

    这道题蛮有意思。

    首先,我们可以将题目转化。题目要求选择特斯拉电磁塔缩进地中,让剩下的塔高度构成等差数列,等价于挑选不缩进地里的塔。

    很显然,DP算法中阶段为塔下标(感觉到)。即可定义以第i个塔为等差数列最后一位时等差数列的个数。(只考虑数列递减的情况,递增的同理)

    然而,对于一个等差数列,极其重要的其实是公差。如果状态中没有公差,则难以转移。

    综上,我们最终定义dp[i, j]指以第i个数为结尾、公差为j的数列个数(“美观”)。
    递增实际上和递减本质一样,程序实现时再来一遍即可。

    转移:首先,第一个想法是枚举公差,再从前面找到能够接在第i个数的位置,累和即可,时间复杂度O((n ^ 2v))
    优化一下。所谓找能够接第i个数前面的位置,实际上就是在确定公差。换句话讲:我们可以通过直接枚举之前的数确定公差,省去了枚举公差的时间。

    另外,实现代码的时候,结果应当在计算过程中累加。

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn = 1000 + 10, mod = 998244353;
    int n, v = 0, h[maxn], dp[maxn][maxn * 20][2],ans=0;
    int main()
    {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++ i)
    	{
    		scanf("%d", &h[i]);
    		v = max(v, h[i]);
    	}
    	for(int i = 1; i <= n; ++ i)
    	{
    		for(int j = 1; j < i; ++ j)
    		{
    			int d = h[i] - h[j];
    			if(d > 0)
    			{
    				dp[i][d][0] = (dp[i][d][0] + dp[j][d][0] + 1) % mod;
    				ans = (ans + dp[j][d][0] + 1) % mod;
    			}
    			else
    			{
    				dp[i][-d][1] = (dp[i][-d][1] + dp[j][-d][1] + 1) % mod;
    				ans = (ans + dp[j][-d][1] + 1) % mod;
    			}
    		}
    		++ ans;
    	}
    	printf("%d
    ", ans % mod);
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu 16.04 not a com32r image
    重定向输出遇到的缓冲问题
    you don't have permission to access / on this server解决
    LaTeX入门简介
    解决eclipse中出现Resource is out of sync with the file system问题
    Ubuntu安装新英伟达驱动出现问题解决方法
    同步与异步的区别
    Cuda入门笔记
    解决 Cocos2d-x 3.2 error C1041: 无法打开程序数据库vc120.pdb
    vs2013编译过程中,错误 59 error C4996: 'GetVersionExW': 被声明为已否决
  • 原文地址:https://www.cnblogs.com/zach20040914/p/13060137.html
Copyright © 2020-2023  润新知