[蓝桥杯 2014 省 A] 波动数列

2023-12-17

题目链接

[蓝桥杯 2014 省 A] 波动数列

题目描述

观察这个数列:

1   3   0   2   − 1   1   − 2   … 1\ 3\ 0\ 2\ -1\ 1\ -2\ … 1 3 0 2 1 1 2

这个数列中后一项总是比前一项 增加 2 2 2 或者 减少 3 3 3 ,且 每一项都为整数

栋栋对这种数列很好奇,他想知道长度为 n n n 和为 s s s 而且后一项总是比前一项增加 a a a 或者减少 b b b 的整数数列可能有多少种呢?

输入格式

共一行,包含四个整数 n , s , a , b n,s,a,b n , s , a , b ,含义如前面所述。

输出格式

共一行,包含一个整数,表示满足条件的方案数。

由于这个数很大,请输出方案数除以 100000007 100000007 100000007 的余数。

数据范围
  • 1 ≤ n ≤ 1000 1≤n≤1000 1 n 1000

  • − 1 0 9 ≤ s ≤ 1 0 9 −10^9≤s≤10^9 1 0 9 s 1 0 9

  • 1 ≤ a , b ≤ 1 0 6 1≤a,b≤10^6 1 a , b 1 0 6

输入样例:

4 10 2 3

输出样例:

2

样例解释

两个满足条件的数列分别是 2   4   1   3 2\ 4\ 1\ 3 2 4 1 3 7   4   1   − 2 7\ 4\ 1\ -2 7 4 1 2

解法:同余 + dp

我们可以列出数列的 n n n 项,这里假设 x x x 是第一项, d 1 , d 2 , . . . , d n − 1 d_1,d_2,...,d_{n-1} d 1 , d 2 , ... , d n 1 的值为 a a a 或者 b b b

s = ( x ) + ( x + d 1 ) + ( x + d 1 + d 2 ) + . . . + ( x + d 1 + d 2 + . . . + d n − 1 ) s = (x) + (x + d_1) + (x + d_1 + d_2) + ... + (x + d_1 + d_2 + ... + d_{n - 1}) s = ( x ) + ( x + d 1 ) + ( x + d 1 + d 2 ) + ... + ( x + d 1 + d 2 + ... + d n 1 )

将其整理一下可以得到 :
s = n × x + ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) s = n \times x + (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1}) s = n × x + ( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )

由于 x x x 可以是任意的整数,而 s s s 是给定的,也就是确定的,于是我们可以通过 s s s 得到 x x x

x = s − [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] n x =\frac{ s -[ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})]}{n} x = n s [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )]

由于 x x x ,也就是数列的第一项,必须是整数。

所以, n n n 必须能够整除 s − [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] s -[ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})] s [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )] ,也就是 s − [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] s -[ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})] s [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )] 除以 n n n 的余数为 0 0 0

我们能够进一步推导出 s s s , [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] [ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})] [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )] 除以 n n n 的余数相等,也就是 s   m o d   n ≡ [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] m o d    n s\ mod\ n \equiv [ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})] \mod n s m o d n [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )] mod n ,即 s s s , [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] [ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})] [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )] 同余 n n n

所以我们将原问题转换为:求使得 [ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( d n − 1 ) ] [ (n - 1)d_1 + (n - 2)d_2 + ... + (d_{n - 1})] [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( d n 1 )] s s s 同余 n n n 的方案数有多少种。

我们定义 f [ i ] [ j ] f[i][j] f [ i ] [ j ] 为从前 i i i 项中选,第 i i i 项元素比前一个 增加 a a a 或者 减少 b b b ,且模 n n n 余数是 j j j 的方案数。

如果第 i i i 项元素选的是 + a +a + a

[ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( n − ( i − 1 ) ) d i − 1 + ( n − 1 ) a ]   m o d   n ≡ j [(n - 1)d_1 + (n - 2)d_2 + ... + (n - (i - 1))d_{i - 1} + (n - 1)a] \ mod\ n \equiv j [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( n ( i 1 )) d i 1 + ( n 1 ) a ] m o d n j

将其转换一下:

[ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( n − ( i − 1 ) ) d i − 1 ]   m o d   n ≡ [ j − ( n − 1 ) a ]   m o d   n [ (n - 1)d_1 + (n - 2)d_2 + ... + (n - (i - 1))d_{i - 1}] \ mod\ n \equiv [j - (n - 1)a] \ mod\ n [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( n ( i 1 )) d i 1 ] m o d n [ j ( n 1 ) a ] m o d n

所以我们可以得到 f [ i ] [ j ] = f [ i − 1 ] [ j − ( n − 1 ) a ] f[i][j] = f[i - 1][j - (n - 1)a] f [ i ] [ j ] = f [ i 1 ] [ j ( n 1 ) a ]

如果第 i i i 项元素选的是 − b -b b

[ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( n − ( i − 1 ) ) d i − 1 − ( n − 1 ) b ]   m o d   n ≡ j [(n - 1)d_1 + (n - 2)d_2 + ... + (n - (i - 1))d_{i - 1} - (n - 1)b] \ mod\ n \equiv j [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( n ( i 1 )) d i 1 ( n 1 ) b ] m o d n j

将其转换一下:

[ ( n − 1 ) d 1 + ( n − 2 ) d 2 + . . . + ( n − ( i − 1 ) ) d i − 1 ]   m o d   n ≡ [ j + ( n − 1 ) b ]   m o d   n [ (n - 1)d_1 + (n - 2)d_2 + ... + (n - (i - 1))d_{i - 1}] \ mod\ n \equiv [j + (n - 1)b] \ mod\ n [( n 1 ) d 1 + ( n 2 ) d 2 + ... + ( n ( i 1 )) d i 1 ] m o d n [ j + ( n 1 ) b ] m o d n

所以我们可以得到 f [ i ] [ j ] = f [ i − 1 ] [ j + ( n − 1 ) b ] f[i][j] = f[i - 1][j + (n - 1)b] f [ i ] [ j ] = f [ i 1 ] [ j + ( n 1 ) b ]

综上,我们可以得出:

f [ i ] [ j ] = f [ i − 1 ] [ j + ( n − 1 ) b ] + f [ i − 1 ] [ j − ( n − 1 ) a ] f[i][j] = f[i - 1][j + (n - 1)b] + f[i - 1][j - (n - 1)a] f [ i ] [ j ] = f [ i 1 ] [ j + ( n 1 ) b ] + f [ i 1 ] [ j ( n 1 ) a ]

注意:

  • 由于 j − ( n − 1 ) a j - (n - 1)a j ( n 1 ) a 可能小于 0 0 0 ,我们必须保证它模 n n n 为正数。令 t = j − ( n − 1 ) a t = j - (n - 1)a t = j ( n 1 ) a ,那么我们最终得到的余数应该是 ( t   m o d   n + n )   m o d   n (t\ mod\ n + n)\ mod\ n ( t m o d n + n ) m o d n ,这样就保证了最终的余数是正数。
  • f [ 0 ] [ 0 ] f[0][0] f [ 0 ] [ 0 ] 应该初始化为 1 1 1 ,因为他表示什么也不选也是一种方案,什么也不选那么就只有第一项 x x x
  • 我们最终返回的答案就是 f [ n − 1 ] [ ( s   m o d   n + n )   m o d   n ] f[n - 1][(s\ mod\ n + n)\ mod\ n] f [ n 1 ] [( s m o d n + n ) m o d n ] ,因为 s s s 有可能是负数,所以我们也需要保证它模 n n n 是一个正数。

时间复杂度: O ( n 2 ) O(n^2) O ( n 2 )

C++代码:

#include <iostream>

using namespace std;

const int N = 1010 , MOD = 100000007;
int f[N][N];

int get_mod(int a , int b){
    return (a % b + b) % b;
}

int main(){
    int n , s, a, b;
    cin>>n>>s>>a>>b;
    
    f[0][0] = 1;
    for(int i = 1;i < n;i++){
        for(int j = 0;j < n;j++){
            int &val = f[i][j];
            val = (val + f[i - 1][get_mod(j - (n - i) * a , n)]) % MOD;
            val = (val + f[i - 1][get_mod(j + (n - i) * b , n)]) % MOD;
        }
    }
    
    cout<<f[n - 1][get_mod(s , n)]<<'\n';
}

Java代码:

import java.io.*;
import java.util.*;

public class Main{
    static final int N = 1010 , MOD = 100000007;
    static long[][] f = new long[N][N];
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    public static int get_mod(int a , int b){
        return (a % b + b) % b;
    }
    
    public static void main(String[] args) throws Exception{
        String[] s1 = in.readLine().split(" ");
        int n = Integer.parseInt(s1[0]);
        int s = Integer.parseInt(s1[1]);
        int a = Integer.parseInt(s1[2]);
        int b = Integer.parseInt(s1[3]);
        
        f[0][0] = 1;
        for(int i = 1;i < n;i++){
            for(int j = 0;j < n;j++){
                f[i][j] = (f[i][j] + f[i - 1][get_mod(j - (n - i) * a , n)]) % MOD;
                f[i][j] = (f[i][j] + f[i - 1][get_mod(j + (n - i) * b , n)]) % MOD;
            }
        }
        
        System.out.println(f[n - 1][get_mod(s,n)]);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[蓝桥杯 2014 省 A] 波动数列 的相关文章

  • 一种关于单片机定时器中断和数码管冲突问题的解决方案

    问题发现 我们会发现 同时存在定时器中断和数码管操作时 有时会导致数码管显示异常 原因探究 在定时器中断函数中不要操作P2和P0 因为定时器 T 和主板 M 的时钟频率不一样 有可能导致M刚操作完P2 T又去操作P0 导致正确的P2和P0没
  • 2022第十三届蓝桥杯国赛真题javaB组

    文章目录 试题A 重合次数 试题B 数数 试题C 左移右移 试题D 窗口 试题E 迷宫 试题F 小球称重 试题G 背包与魔法 试题H 修路 试题I 围栏 试题J 好数之和 试题A 重合次数 本题总分 5 分 问题描述 在同一天中 从上午6
  • 蓝桥杯 题库 简单 每日十题 day2

    01 卡片 题目描述 本题为填空题 只需要算出结果后 在代码中使用输出语句将所填结果输出即可 小蓝有很多数字卡片 每张卡片上都是数字 0 到 9 小蓝准备用这些卡片来拼一些数 他想从 1 开始拼出正整数 每拼一个 就保存起来 卡片就不能用来
  • 蓝桥杯 辗转相除法---求最大公约数

    1 例子 例如 求 319 377 319 377 0 余319 319 377 377 319 377 319 1 余58 377 319 319 58 319 58 5 余29 319 58 58 29 58 29 2 余0 58 29
  • 青少年ptyhon可以参加的主流比赛大全

    青少年python教学视频ppt源码 青少年python系列目录 老程序员115的博客 CSDN博客 一 全国青少年软件编程等级考试 主办单位 中国电子学会 全国青少年电子信息科普创新联盟 网址 http www qceit org cn
  • 蓝桥杯---貌似化学---逆矩阵

    试题 算法训练 貌似化学 资源限制 时间限制 1 0s 内存限制 256 0MB 问题描述 现在有a b c三种原料 如果他们按x y z混合 就能产生一种神奇的物品d 当然不一定只产生一份d 但a b c的最简比一定是x y z 现在给你
  • c1048: [编程入门]自定义函数之字符串拷贝

    题目描述 有一字符串 包含n个字符 写一函数 将此字符串中从第m个字符开始的全部字符复制成为另一个字符串 输入 数字n 一行字符串 数字m 输出 从m开始的子串 样例输入复制 6 abcdef 3 样例输出复制 cdef 思路 两种方法 一
  • 蓝桥杯最长不下降子序列,线段树python

    问题描述 给定一个长度为 N 的整数序列 A1 A2 AN 现在你有一次机会 将其 中连续的K 个数修改成任意一个相同值 请你计算如何修改可以使修改后的数 列的最长不下降子序列最长 请输出这个最长的长度 最长不下降子序列是指序列中的一个子序
  • c++汉诺塔蓝桥杯

    总时间限制 10000ms 单个测试点时间限制 1000ms 内存限制 262144kB 描述 小蓝很喜欢玩汉诺塔游戏 游戏中有三根柱子 开始时第一根柱子上有 n 个圆盘 从上到下圆盘的大小依次为 1 到 n 每次 可以将一个盘子从一根柱子
  • 树与二叉树(二叉树的表示,性质,遍历,还原)

    1 基本术语 A 或B 是I的祖先 I是A 或B 的子孙 D是I的双亲 I是D的孩子 节点的孩子个数称为节点的度 树中节点的最大度数称为树的度 度大于0的节点称为分支节点 度等于0的节点称为叶节点 定义树根为第一层 则 树的深度 高度 为5
  • 编程之美2015初赛第二场AB

    题目1 扑克牌 时间限制 2000ms 单点时限 1000ms 内存限制 256MB 描述 一副不含王的扑克牌由52张牌组成 由红桃 黑桃 梅花 方块4组牌组成 每组13张不同的面值 现在给定52张牌中的若干张 请计算将它们排成一列 相邻的
  • 蓝桥杯每日一题2023.9.16

    蓝桥杯2022年第十三届省赛真题 X进制减法 C语言网 dotcpp com 题目描述 进制规定了数字在数位上逢几进一 X 进制是一种很神奇的进制 因为其每一数位的进制并不固定 例如说某种 X 进制数 最低数位为二进制 第二数位为十进制 第
  • 动态规划之多重背包模型

    前置知识 01背包问题 动态规划之01背包模型 如何何何的博客 CSDN博客 完全背包问题 动态规划之完全背包模型 如何何何的博客 CSDN博客 多重背包问题 给定一个有一定容量的背包 和 n 个物品 每个物品有 si 件 每个物品有其对应
  • 蓝桥杯-稍大的字符串

    题目 标题 稍大的串 串可以按照字典序进行比较 例如 abcd 小于 abdc 如果给定一个串 打乱组成它的字母 重新排列 可以得到许多不同的串 在这些不同的串中 有一个串刚好给定的串稍微大一些 科学地说 它是大于已知串的所有串中最小的串
  • 蓝桥杯 填字母游戏(博弈论)

    小明经常玩 LOL 游戏上瘾 一次他想挑战K大师 不料K大师说 我们先来玩个空格填字母的游戏 要是你不能赢我 就再别玩LOL了 K大师在纸上画了一行n个格子 要小明和他交替往其中填入字母 并且 1 轮到某人填的时候 只能在某个空格中填入L或
  • 【快速选择算法】O(n)时间复杂度

    快速选择的期望时间复杂度为O n 最坏时间复杂度为O n 2 当每次划分只划分为n 1个和1个时 由于划分时间复杂度为O n 最坏时间复杂度为O n 2 void quickselect vector
  • codeforces 102263 J

    题目 一开始贪心 直接枚举每个位置 一直wa 不知道错哪里了 后来才发现是dp 很多种情况是无法直接贪心的 设 d p i 0
  • 2021年12月-电子学会青少年等级考试C语言(一级)真题与解析

    2021年12月软件编程 C语言 等级考试 一级 分数 100 题数 5 时间限制 1000 ms 内存限制 65536 kB 1 输出整数部分 题目描述 输入一个双精度浮点数 输出其整数部分 输入 一个双精度浮点数f 0 lt f lt
  • 插入数计数类 / 转为换行类dp:AT_agc024_e

    https www luogu com cn problem AT agc024 e 首先题目可以转化成每次插入一个数 满足字典序递增 如果只考虑暴力dfs 先别上dp 想想怎么合法和不算重 合法 也就是插入数有3种情况 插到末尾 插到比他
  • 字符串处理-第11届蓝桥杯省赛Python真题精选

    导读 超平老师的Scratch蓝桥杯真题解读系列在推出之后 受到了广大老师和家长的好评 非常感谢各位的认可和厚爱 作为回馈 超平老师计划推出 Python 蓝桥杯真题解析100讲 这是解读系列的第26讲 字符串处理 本题是2020年6月20

随机推荐