等差数列

P4933 大师 题解

我们两清 提交于 2020-04-06 22:02:03
CSDN同步 原题链接 简要题意: 求一个数列中有多少个等差子序列。(子序列 不一定连续 ,子串 一定连续 ) 注:公差可以是负数。 算法一 对于 \(30 \%\) 的数据, \(n \leq 20\) . 显然,枚举子序列,然后暴力验证。 时间复杂度: \(O(2^n \times n)\) . 实际得分: \(30pts\) . 算法二 对于 \(60 \%\) 的数据, \(n \leq 100\) , \(v \leq 2 \times 10^3\) . 枚举等差数列前 \(2\) 项,然后算出公差,往后枚举即可。 时间复杂度: \(O(n^3)\) . 实际得分: \(60pts\) ~ \(100pts\) .(取决于程序常数) 算法三 对于另外 \(20 \%\) 的数据,所有电塔的高度构成一个等差数列。 显然,这时答案就相当于在 \(1\) ~ \(n\) 中取等差数列。 为什么呢?这时,只要取等差数列 \(x, x+y , x+y \cdots x+ky\) ,则在 原数列 中对应的数列为: \[a_x , a_{x+y} \cdots a_{x+ky} \] 必然为等差数列,并且每个数列对应一个这样的 等差数列 。 那么,你用上面 \(60 \%\) 的暴力优化一下,枚举任意的两个点都可以形成等差数列,计算即可。 当然有一种特殊情况:即 \(a_i = a_j

我的第一篇题解

六眼飞鱼酱① 提交于 2020-03-21 01:10:29
人生第一次写题解 更好阅读体验,请点击 这里 简单分析题目之后,发现这个题就是要我们求原数列中有多少等差子数列。 观察了数据范围之后发现,本题目给出了最大高度的范围。要知道给出数据范围的量是 很有可能 出现在正解复杂度里的(时间或空间),所以我们尽量往这两个上面靠。由于做题不多,所以我想从仅做过的几个模板题里面借鉴一些思路来解决这个问题。这是本蒟蒻第一篇题解,前面叙述了思路历程,可能前面部分较为啰嗦,想直接看可$AC$做法的可以看后面的部分。 状态定义 由于dp的题目我们可以考虑定义前i个元素中选择组成的序列($LCS$)或者以i为结尾的序列($LIS$)的某个性质的量度(比如$LCS$长度)为$f[i]$,当然也可能由于题目有约束$j$(比如背包中的容量),所以就成了定义$f[i][j]$为我们想要的状态。在本题中,我先是思考$f[i]$为 前i个 元素中选择能够组成的等差数列的个数,因为看起来对于$i-1<i$, $f[i]$的组成的一部分就是$f[i-1]$,也就是前i个元素中必定不选第$i$个元素时的等差子数列数,那么必然包含第i个元素的时候又是怎样一个结果呢?为了计算这个,我们可能要知道$f[i-1]$里面的各种等差子数列的公差细节以及结尾,并根据$a[i]$的情况看能否组成等差数列,与我们之前见到的简洁的dp转移不符,暂时放弃此思路。 有了刚才的经验,我们发现可能定义

LeetCode 413.等差数列划分

爷,独闯天下 提交于 2020-03-11 01:07:03
如果[1,2,3,4,5,6]是一个等差数列,则 以A[2]结尾的等差数列 [1,2,3] 以A[3]结尾的等差数列 [1,2,3,4],[2,3,4] 以A[4]结尾的等差数列 [1,2,3,4,5],[2,3,4,5],[3,4,5] 以A[5]结尾的等差数列 [1,2,3,4,5,6],[2,3,4,5,6],[3,4,5,6],[4,5,6] 设 f[i] 以 A[i] 为结尾的等差数列的个数。 答案为 f[] 数组的总和 class Solution { public int numberOfArithmeticSlices ( int [ ] A ) { int n = A . length ; if ( n < 3 ) return 0 ; int [ ] f = new int [ n ] ; int res = 0 ; for ( int i = 2 ; i < n ; i ++ ) { if ( A [ i ] - A [ i - 1 ] == A [ i - 1 ] - A [ i - 2 ] ) f [ i ] = f [ i - 1 ] + 1 ; res += f [ i ] ; } return res ; } } 来源: CSDN 作者: Coldc0 链接: https://blog.csdn.net/qq_43118676/article

东华oj-进阶题第45题-等差数列

吃可爱长大的小学妹 提交于 2020-03-07 20:05:17
45 等差数列 作者: xxx时间限制: 1S章节: 一维数组 问题描述 : 一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。 写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。 输入说明 : 第一行: N(3<= N<=25),要找的等差数列的长度。 第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。 输出说明 : 如果没有找到数列,输出`NONE’。 如果找到了,输出一行或多行, 每行由两个整数组成:a,b 这些行应该先按b排序再按a排序(均为升序)。 将不会有多于10,000个等差数列。 输入范例 : 5 7 输出范例 : 1 4 37 4 2 8 29 8 1 12 5 12 13 12 17 12 5 20 2 24 代码: /* T45 等差数列 算法概述:设置一个标记数组,用于标记某个数是否为双平方数。 对于每一个a,b,测试它们确定的一个长度为N的等差数列的每一项 是否为双平方数,若测试通过,则输出a,b,否则进行下一次测试。 */ # include <stdio.h> # include <string.h> # define MAX_SIZE 250 * 250 * 2 int

等差数列

痞子三分冷 提交于 2020-03-05 00:25:22
/* 题目描述 如果一个数列S满足对于所有的合法的i,都有S[i + 1] = S[i] + d, 这里的d也可以是负数和零,我们就称数列S为等差数列。 小易现在有一个长度为n的数列x,小易想把x变为一个等差数列。小易允许在数列上做交换任意两个位置的数值的操作,并且交换操作允许交换多次。但是有些数列通过交换还是不能变成等差数列,小易需要判别一个数列是否能通过交换操作变成等差数列 输入描述: 输入包括两行,第一行包含整数n(2 ≤ n ≤ 50),即数列的长度。 第二行n个元素x[i](0 ≤ x[i] ≤ 1000),即数列中的每个整数。 输出描述: 如果可以变成等差数列输出"Possible",否则输出"Impossible"。 示例1 输入 复制 3 3 1 2 输出 复制 Possible */ #include<stdio.h> int main(int argc,char *argv[]) { int n,i,t,t1,j; scanf("%d",&n); int cnt=0; int a[n]; for(i=0;i<n;i++) { scanf("%d",&a[i]); } for(i=0;i<n-1;i++) { for(j=0;j<n-1-i;j++) { if(a[j+1]<a[j]) { t=a[j+1]; a[j+1]=a[j]; a[j]=t; } } }

进阶45-等差数列

你离开我真会死。 提交于 2020-03-03 15:51:05
一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。 写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。 输入:第一行: N(3<= N<=25),要找的等差数列的长度。 第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。 输出:如果没有找到数列,输出`NONE’。 如果找到了,输出一行或多行, 每行由两个整数组成:a,b 这些行应该先按b排序再按a排序(均为升序)。将不会有多于10,000个等差数列。 5 7 1 4 37 4 2 8 29 8 1 12 5 12 13 12 17 12 5 20 2 24 这道题初看思路很好理解,只需要先找到平方数的集合,然后从集合选中数,求差距,不断向上递增,查看长度为n的数列是否在集合中即可。 当m比较小的时候还能快速求解,但当m比较大的时候,由于求解对比的数量大大增加后,就很容超时(就是被这个超时难受的抓头),后来经过初步优化是间隔b最大的取值为(集合最大值-选取的数列首个元素)/ 数列长度,时间优化了一些,但还是不能解决m过大时的超时问题,之后再查看了一些文章后,找到了关键的优化 : if(vi[i]+(vi[j]-vi[i])*(n-1) > vi[len-1]

413. 等差数列划分

て烟熏妆下的殇ゞ 提交于 2020-02-23 03:13:26
413. 等差数列划分 1.题目描述 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。 例如,以下数列为等差数列: 以下数列不是等差数列。 数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。 如果满足以下条件,则称子数组(P, Q)为等差数组: 元素 A[P], A[p + 1], …, A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。 函数要返回数组 A 中所有为等差数组的子数组个数。 示例: 2.思路(动态规划) dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。当 A[i] - A[i-1] == A[i-1] - A[i-2],那么 [A[i-2], A[i-1], A[i]] 构成一个等差递增子区间。而且在以 A[i-1] 为结尾的递增子区间的后面再加上一个 A[i],一样可以构成新的递增子区间。 dp[2] = 1 [0, 1, 2] dp[3] = dp[2] + 1 = 2 [0, 1, 2, 3], // [0, 1, 2] 之后加一个 3 [1, 2, 3] // 新的递增子区间 dp[4] = dp[3] + 1 = 3 [0, 1, 2, 3, 4], // [0, 1, 2, 3] 之后加一个 4 [1, 2,

最大等差数列子集

我怕爱的太早我们不能终老 提交于 2020-02-23 01:15:14
13 最大等差数列子集 描述 一个等差数列是指以增序排列后,相邻的两个数后一个与前一个数之差值恒定。规定一个等差数列中的数不应少于3个。任给 n ( 2 < n < 5000)个正整数,请判断可否从中选择子集构成等差数列。若能,则选出满足条件的最大子集合(即,元素个数最多),并按从小到大输出子集中的元素,逗号间隔。若有多个子集同时满足最大,则取差值最大的子集;若同时有多个子集满足集合大小最大,且差值也相等,则取起始元素最大的子集。如果没有满足条件的子集合,则输出 NO. 关于输入 第1行,n,表示整数个数; 第2行,n 个正整数,空格间隔; 关于输出 按增序输出最长等差数列子集,逗号间隔。 例子输入 10 20 14 6 15 22 7 23 8 18 25 例子输出 7,15,23 分析 ​ 显而易见的,我们首先要对这个序列排序。在这里我们需要对 [ 结 尾 元 素 序 号 ] [ 数 列 公 差 ] [结尾元素序号][数列公差] [ 结 尾 元 素 序 号 ] [ 数 列 公 差 ] 进行dp,递推公式 ​ d i f f = a r r [ i ] − a r r [ j ] diff = arr[i] - arr[j ] d i f f = a r r [ i ] − a r r [ j ] d p [ i ] [ d i f f ] = d p [ j ] [ d i f

413等差数列划分

て烟熏妆下的殇ゞ 提交于 2020-02-12 21:40:43
题目:如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。 例如,以下数列为等差数列: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9 以下数列不是等差数列。1, 1, 2, 5, 7 数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。 如果满足以下条件,则称子数组(P, Q)为等差数组: 元素 A[P], A[p + 1], ..., A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。 函数要返回数组 A 中所有为等差数组的子数组个数。 链接:https://leetcode-cn.com/problems/arithmetic-slices 法一:自己的代码 思路:由于是求子数组个数就很简单, 动态转移方程:dp[i][0] = arr[i] - arr[i-1]即arr中第i个数减第i-1个数的差,dp[i][1]是以arr[i]结尾的等差数列的个数加2,所以dp[i][1]-2即为数列个数 。 from typing import List class Solution: def numberOfArithmeticSlices(self, A: List[int]) -> int: res = 0 size =