[蓝桥杯 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] 波动数列 的相关文章

  • 蓝桥杯 辗转相除法---求最大公约数

    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
  • 【Java】用do-while循环,实现猜数字。

    package TcmStudy day05 import java util Scanner public class DoWhileText01 public static void main String args Scanner i
  • 备战2023蓝桥国赛-饼干

    题目描述 解析 这道题我想了很多种解决方法 但无一例外都失败了 实在是按照常规线性DP的思路真的想不出来 看了题解之后才知道它是分为三步解决这个问题的 第一步 缩小最优解的范围 先用贪心将最优解缩小到某个较小的范围内 再DP求出精确的最优解
  • 洛谷P1028 [NOIP2001 普及组] 数的计算 —— 简单DP+双指针优化

    This way 题意 给出自然数 n n n 要求按如下方式构造数列 只有一个数字 n n n 的数列是一个合法的数列 在一个合法的数列的末尾加入一个自然数 但是这个自然数不能超过该数列最后一项的一半 可以得到一个新的合法
  • xml转义字符

    在mybatis在编写sql时不能在XML里直接使用 lt 或者是 gt 在这里需要使用转义字符替换 下面列举常用的xml转义对应 1 lt lt 小于号 2 gt gt 大于号 3 amp 和 4 apos 单引号 5 quot 双引号
  • Thief in a Shop 【CodeForces - 632E】【背包】

    题目链接 给了N个物品 每个物品无限个 我们要的是求刚好我们拿了K个物品的时候 能组成哪几种数 我们可以想个办法去填充 那么就需要有一个所谓的0状态 然后假如不足K个的时候 就可以拿这个所谓的0状态来填充了 所以 我们把所有的数排序 然后都
  • 过河卒 蓝桥杯 755

    题目描述 如图 A 点有一个过河卒 需要走到目标 B 点 卒行走规则 可以向下 或者向右 同时在棋盘上的 C 点有一个对方的马 该马所在的点和所有跳跃一步可达的点称为对方马的控制点 例如上图 C 点上的马可以控制 99 个点 图中的 P1
  • Java语言 ASCII to Hex 互转(IOT-示例)

    概述 最近想起之前做的IOT项目 使用JAVA写了一个
  • 1093: 数1的个数

    存限制 128 MB 题目描述 给定一个十进制正整数n 1 n 10000 写下从1到n的所有整数 然后数一下其中出现的数字 1 的个数 例如当n 2时 写下1 2 这样只出现了1个 1 当n 12时 写下1 2 3 4 5 6 7 8 9
  • 蓝桥杯 成绩统计

    目录 问题描述 思路分析及代码实现 问题描述 小蓝给学生们组织了一场考试 卷面总分为 100 分 每个学生的得分都是一个 0 到 100 的整数 如果得分至少是 60 分 则称为及格 如果得分至少为 85 分 则称为优秀 请计算及格率和优秀
  • 蓝桥杯-2020年省赛-回文日期

    498 import datetime n input start datetime date int n 4 int n 4 6 int n 6 delta datetime timedelta days 1 flag 0 for i i
  • c++类和对象--封装--属性和行为做整体

    封装的意义 1 将属性和行为当做一个整体来表现对象 类中的属性和行为统称为成员 属性又叫成员属性或成员变量 行为又叫成员函数或成员方法 案例 设计一个圆类 求圆的周长 include
  • UVa 1347 Tour

    题目 Tour 题意 来自luogu John Doe想用最小的路程游览完所有目的地 每个目的地都用坐标xi yi表示 任何两目的地的xi都不相同 两目的地之间的路程是两点之间的直线距离 John是这样走的 他从最左边的点开始 然后只能向右
  • 1141 二维数组的输入和输出

    题目描述 输入m行n列的二维数组的值 再按行列形式输出 输入要求 第一行输入m n代表行数和列数 接着输入具体的m n个元素 输出要求 按行列形式换行输出 每一个数据后面都有空格 一行输出完毕后换行 输入样例 2 5 1 4 6 23 1
  • 2022年第十四届蓝桥杯模拟赛【核酸日期】C语言详解

    目录 题目 思路 代码实现 题目 核酸日期 问题描述 如果周一做核酸 周二显示核酸天数为 1 天 周三显示 2 天 以此类推 周六显示 5 天 周日显示 6 天 小蓝在某一天做了一次核酸 请问他的核酸显示为几天 已知做核酸和查看核酸不是在同
  • Open Camera异常分析(一)

    负责的项目中遇到一些三方和其他的场景使用camera导致问题 并且没有及时释放camera device致使手机camera应用一直无法使用的严重问题 针对这类问题进行了一系列的分析与追踪 最后算是定位到了问题且提供了一些解决方案 但整个追
  • 第14届蓝桥杯C++B组省赛

    文章目录 A 日期统计 B 01 串的熵 C 冶炼金属 D 飞机降落 E 接龙数列 F 岛屿个数 G 子串简写 H 整数删除 I 景区导游 J 砍树 今年比去年难好多 Update 2023 4 10 反转了 炼金二分没写错 可以AC了 U
  • 第十二届蓝桥杯 2021年省赛真题 (Java 大学C组) 第二场

    蓝桥杯 2021年省赛真题 Java 大学C组 第二场 A 浮点数 B 求余 C 双阶乘 D 格点 E 整数分解 F 3 的倍数 G 特殊年份 H 小平方 I 完全平方数 J 负载均衡 A 浮点数 题目 问题描述 IEEE 754 规定一个
  • 插入数计数类 / 转为换行类dp:AT_agc024_e

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

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

随机推荐