等差数列

维护区间加等差数列的求和问题

非 Y 不嫁゛ 提交于 2020-02-09 12:59:34
这里直接以luogu上的一道了例题为例: https://www.luogu.com.cn/problem/P1438 题目描述 维护一个数列{a[i]},支持两种操作: 1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D, a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。 2、2 P:询问序列的第P个数的值a[P]。 输入格式 第一行两个整数数n,m,表示数列长度和操作个数。 第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。 接下来的m行,表示m个操作,有两种形式: 1 L R K D 2 P 字母意义见描述(L≤R)。 输出格式 对于每个询问,输出答案,每个答案占一行。 输入输出样例 输入 #1 复制 5 2 1 2 3 4 5 1 2 4 1 2 2 3 输出 #1 复制 6 说明/提示 数据规模: 0≤n,m≤100000 |a[i]|,|K|,|D|≤200 思路: 设原数组为a,考虑对a进行差分,对于 差分数组d, a[p] = d[1] + d[2] + ... + d[p] ,而对a[l]~a[r]加上等差数列的值,在数组d上的修改为: d[l] = a[l] - a[l - 1]

顺序表练习(四):上三角矩阵的压缩存储公式推导以及代码实现

孤者浪人 提交于 2020-01-23 05:50:19
前言 本篇博客会较为详细地讲一下我个人对三角矩阵压缩存储公式的理解,希望能给后面的朋友们带来一些帮助。 等差数列的求和公式 由于三角矩阵的压缩存储公式是依靠求和公式来推导的,所以得先补一下等差数列的求和公式。 求和公式一: 其中n是整个数列的项数, 是数列的首项,d是数列的公差(递增数列公差为正数,递减数列公差为负数)。 求和公式二: 其中n为整个数列的项数, 是数列的首项, 是数列的末项。下面主要用到这个公式二。 上三角矩阵压缩储存公式的推导 首先我们知道,压缩储存上三角矩阵,本质上就是将矩阵的上三角块的元素“展开”成一条长的数列存在数组里。问题就在于,我们 如何根据原矩阵里元素的行号和列号得到压缩后数组里对应的下标? 我们可以这样考虑: 对于一个上三角块里第i行第j列的元素 ,它在数组里的下标就等于(在原矩阵中)他前面i-1行的元素数量 + (原矩阵中)他所在行的他前面的元素数量 ,以下面这个矩阵为例, 在数组里的位置就应该是它前面两行元素的数量5+4=9,再加上 所在行它前面的元素数量1(即是 ),最终结果10即是 在数组中的位置(当然,转换成物理下标的话还需要-1)。 那么问题又来了, 我们如何才能知道前面1到i-1行的元素数量? 这个时候就要用到我们的等差数列求和公式了,我们可以从上到下地将每行的 元素数量 看成一个数列,对于上图的矩阵来说,这个数列就是5 4 3 2 1

尼科彻斯定理

孤街浪徒 提交于 2020-01-22 07:38:04
[ 编程题 ]- 尼科彻斯定理 【解题思路】 该题目本身不难,考察数学功底。 1 ^ 3 = 1 2 ^ 3 = 3 + 5 3 ^ 3 = 7 + 9 + 11 4 ^ 3 = 13 + 15 + 17 + 19 观察规律,总结归纳,连续奇数求和就是等差数列求和,难点立即转换为等差数列的首项,得出首项 a = m* (m- 1 )+ 1 【示例代码】 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Main { public static void main(String[] args) throws IOException{ BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); String s; while((s=bf.readLine())!=null){ long m = Integer.valueOf(s); long a = m*m-m+1;//计算首项 System.out.print(a); for(int i=1; i<m; i++){//继续等差数列求和 System.out.print("+"+(a+=2

17A_3等差数列问题

时光毁灭记忆、已成空白 提交于 2020-01-17 02:50:36
题目描述: 键盘输入一个有序正项数列,以空格作为间隔符。计算该序列中包含的最长等差子序列的长度,输出长度以及序列。 sample input: 1 2 3 5 7 8 14 20 26 sample output: 5 2 8 14 20 26 测试结果: 思路: 本题目应该可以用动态规划解,但是没想出来,用的DFS的思路。 AC代码 # include <stdio.h> # define maxn 100 typedef struct { int a [ maxn ] ; int len ; } Node ; Node temp , ans ; int test [ maxn ] ; int n ; //一共有n个元素 int max = 0 ; int isAS ( ) //判断是否为等差数列 { if ( temp . len <= 2 ) return 1 ; //temp的数组len长度小于等于2时 if ( ( temp . a [ temp . len - 1 ] - temp . a [ temp . len - 2 ] ) == ( temp . a [ temp . len - 2 ] - temp . a [ temp . len - 3 ] ) ) return 1 ; //temp的数组len长度大于等于3时 return 0 ; //其他情况不是 }

等差数列,for循环,递归和尾递归的对比

╄→尐↘猪︶ㄣ 提交于 2020-01-14 16:03:35
生活中,如果1+2+3+4.....+100,大家基本上都会用等差数列计算,如果有人从1开始加,不是傻就是白X,那么程序中呢,是不是也是这样。今天无意中看到了尾递归,以前也写过,但是不知道这个专业名词,今天写一下对比下性能问题。 今天主要是看到了尾递归,所以联想到了这些,写下这篇文章,其中也把Benchmark (Nuget上的BenchmarkDotNet)的基准测试用了下,感觉比较好用,赞。Benchmark 需要在release下运行。 原则上所有的递归操作,都可以写成循环操作。尾递归是指,在函数返回的时候,调用自身本身,并且return语句不能包含表达式。这样编译器或者解释器就可以把尾递归做优化,试运行速度更快。 测试类 public class TestClass { /// <summary> /// for循环 /// </summary> /// <param name="n"></param> /// <param name="counter"></param> /// <returns></returns> public int TestFor(int n) { int s = 1; for (int i = 2; i < n + 1; i++) { s = s + i; } return s; } /// <summary> /// 等差数列 /// <

欢乐赛J

人走茶凉 提交于 2020-01-14 09:14:46
CF1278B 原题链接https://vjudge.net/contest/350953#problem/J 方程就是这么个方程,关于(x+1)*x/2,是等差数列前x项和,abs是绝对值,这个函数有可能被编译器报错,自己手写一个外部函数来返回绝对值就好, 第三行是等号左边将-b合并进去,就是这个规律,,直接判断一下就好, # include <algorithm> # include <cmath> # include <cstdio> # include <cstdlib> # include <cstring> # include <iostream> # include <queue> # include <stack> using namespace std ; int main ( ) { long long t ; scanf ( "%lld" , & t ) ; while ( t -- ) { long long a , b ; scanf ( "%lld %lld" , & a , & b ) ; long long i ; for ( i = 0 ; ; i ++ ) { long long sum = ( i + 1 ) * i / 2 ; if ( sum >= abs ( a - b ) && ( sum + abs ( a - b ) ) % 2 =

切蛋糕

瘦欲@ 提交于 2020-01-13 16:36:32
有5个小朋友分一个蛋糕,只能切3刀,怎样才能平均呢?答:一刀砍死一个小朋友,然后两刀分成4块。咳咳,开个玩笑。 题意:用n个平面最多能把空间分成多少块。这是我第一次在比赛现场推出一道数学题,表示内牛满面。 要解决这题,可先从它低一级的问题入手,即:n条直线最多能把平面分成多少块。这个很容易想,如果已有x条线,则第X+1条直线最多与原有直线交得X个点,将这条直线分成X+1段,其中每段都把一个原有块分成两块,所以增加了X+1块,即:f(x+1) - f(x) = x+1。f(x)就是一个二阶等差数列。 然后再回到三维问题,同理,第X+1个平面与原有平面最多交得X条直线,当这X条直线在新平面上形成的图形满足二维最优解时,第X+1个平面被分成最多个小块,而这些小块分别把三维空间上一个小块分为两部分,bulabulabula……所以F(x+1) - F(x) = f(x),F(x)就是一个三阶等差数列。 目测如果这题上升到四维的话,公式就是四阶等差数列了,不过那种情形就不是我能想象的了╮(╯▽╰)╭ 来源: https://www.cnblogs.com/lzxskjo/archive/2013/05/05/3061690.html

1027. 最长等差数列

蹲街弑〆低调 提交于 2019-12-17 10:00:00
题意: 给定一个整数数组 A,返回 A 中最长等差子序列的长度。 回想一下,A 的子序列是列表 A[i_1], A[i_2], …, A[i_k] 其中 0 <= i_1 < i_2 < … < i_k <= A.length - 1。并且如果 B[i+1] - B[i]( 0 <= i < B.length - 1) 的值都相同,那么序列 B 是等差的。 思路: dp[i][j]表示A[i]的前面公差为j的数量 则若A[X]-A[i] == j 则dp[x][j] = dp[i][j]+1 再维护一个最大序列 code: class Solution : def longestArithSeqLength ( self , A : List [ int ] ) - > int : max_l = 0 diff_dict = { } for i in range ( 0 , len ( A ) ) : diff_dict [ i ] = { } for j in range ( 0 , i ) : diff = A [ i ] - A [ j ] if diff not in diff_dict [ j ] : diff_dict [ i ] [ diff ] = 2 else : diff_dict [ i ] [ diff ] = diff_dict [ j ] [ diff

@codeforces - 932G@ Palindrome Partition

旧街凉风 提交于 2019-12-11 19:09:54
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个字符串 s,求有多少种方案可将其划分成偶数个段 \(p_1, p_2, ..., p_k\) ,使得 \(p_i = p_{k-i+1}\) 。 模 10^9 + 7。 2 ≤ |s| ≤ 10^6。 原题戳这里 。 @solution@ 回文划分有一个经典的做法。不过这道题并不完全是回文划分,需要进一步地转化。 构造串 t = \(s_1s_ns_2s_{n-1}...\) ,则对 t 的偶回文划分对应了原题的一个合法划分。 定义 dp[i] 表示前 i 个字符进行回文划分的方案数。因为要偶回文划分,所以假如 i 为奇数直接令 dp[i] = 0。 朴素的转移即构建回文自动机,求出以 i 为结束的所有回文串,然后把这些回文串进行转移。 考虑是否可以利用之前已经处理过的信息。如图: 假如有若干回文串的长度形成以 d 为公差的等差数列(如图黑色线段),我们可以取 i-d 已经计算过的值(如图蓝色线段)方便我们转移。 具体一点,对于回文自动机上每一个结点 x,记 d(v) = len(v) - len(fa(v)),将 d(v) 相同的连续段称作一个等差数列(注意这里等差数列的定义)。 点 x 的最后更新位置 t 指的是,在前缀 t

等差数列的划分

萝らか妹 提交于 2019-12-10 18:36:27
等差数列的划分 题目 破题 解题 题目 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。 例如: 以下数列为等差数列: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9 以下数列不是等差数列: 1, 1, 2, 5, 7 破题 最直接的方法: 很容易知道A[P] ~ A[Q]是等差数列的前提是A[P] ~ A[Q-1]也是等差数列,并且A[Q] - A[Q - 1] = d(公差)。按照数学的角度讲,只有一个数字和有两个数字的数列也是等差数列,但是题目中要求包含三个元素。 解题 class Solution { public int numberOfArithmeticSlices ( int [ ] A ) { int length = A . length ; if ( length < 3 ) return 0 ; //dp[p][q] == true 表示A[P]~A[Q]为等差数列 boolean [ ] [ ] dp = new boolean [ length ] [ length ] ; int count = 0 ; for ( int q = 1 ; q < length ; q ++ ) { for ( int p = 0 ; p < q ; p ++ ) { /