(排列,选择类dp)(数论同余定理,同余运算)(以背包为母题)1214. 波动数列

简介: (排列,选择类dp)(数论同余定理,同余运算)(以背包为母题)1214. 波动数列

1214. 波动数列 - AcWing题库


// 卡壳,漏了题目关键流程要取模,由于是例题就没有按流程debug导致

// 错误:i的范围应该是1到n-1,因为数组的第一项是任意的,且已经分离出去了,这里只有第二项开始往后的数

// 卡壳,j的范围没有确定好,模n余数应该是0到n-1

// 错误取模的数错误,这里数组保存的是题目结果,应该模 100000007,n是对于下标才要模的数

dp分析时,在分析状态表示时,要分析每一维的取值范围

最后检查范围时,不仅要检查数据范围,还要检查取模情况

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
// // c++中的负数取模会得到负数,但数学中的负数取模是应该得到正数的,要写上一个取模函数把负数取模补正
int get_mod(int a,int b){
    return (a % b + b) % b;
}
// 卡壳,漏了题目关键流程要取模,由于是例题就没有按流程debug导致
const int N = 1e3 + 10,MOD =  100000007;
int f[N][N];
int main(){
    int n,s,a,b;
    cin >> n >> s >> a >> b;
    f[0][0] = 1;
    for(int i = 1;i <= n;i++){
        // 错误:i的范围应该是1到n-1,因为数组的第一项是任意的,且已经分离出去了,这里只有第二项开始往后的数
        for(int j = 0;j <= n;j++){ 
            // 卡壳,j的范围没有确定好,模n余数应该是0到n-1
            f[i][j] = (f[i-1][get_mod(j-(n-i)*a,n)] + f[i-1][get_mod(j + (n-i)*b,n)]) % MOD; 
            // 错误取模的数错误,这里数组保存的是题目结果,应该模 100000007,n是对于下标才要模的数
        }
    }
    cout << f[n-1][get_mod(s,n)];
    // 错误,同i范围没有确定的连带错误
    return 0;
}

思路

// 1≤n≤1000

// ,

// −109≤s≤109

// ,

// 1≤a,b≤106

// 范围在暗示用枚举类的方法,想dfs,dp

// 观察这个数列:


// 1 3 0 2 -1 1 -2 …


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


// 栋栋对这种数列很好奇,他想知道长度为 n

// 和为 s

// 而且后一项总是比前一项增加 a

// 或者减少 b

// 的整数数列可能有多少种呢?

// 表达式


// x + x + d1 + x + d1 + d2 + x + d1 + d2 + d3 + ... = s;

// s = n*x + (n-1)d1 + (n-2)d2 + (n-3)*d3 + ...;

// x无限制,用有限制的量来表示

// s - ((n-1)d1 + (n-2)d2 + (n-3)*d3 + ...) / n = x;

// 因为x是整数,所以

// s - ((n-1)d1 + (n-2)d2 + (n-3)*d3 + ...)一定是n的倍数

// 根据?同余定理,

// s 同余 ((n-1)d1 + (n-2)d2 + (n-3)*d3 + ...) (mod n)

// 看((n-1)d1 + (n-2)d2 + (n-3)*d3 + ...),要枚举每一个d选a还是b,可以开始dp分析,

// 两个选择的dp,排列问题dp,选择问题dp,(母题为背包问题)


// // 状态表示 f[i][j] 二维数组表示考虑前i项,j表示余数的情况数

// // 属性 :情况数

// 情况数属性要边界初始化

// // // 状态表示写的时候考虑好取值范围


// // i范围是1到n-2,因为这里通过变换把第一项给去掉了,所以少一项

// // j的范围,0到n

// // 状态计算 集合划分,最后一项不同的,f[i][j],第i项选a f[i-1][j-(n-1)*a]

// // 第i项选b f[i-1][j+(n-1)*b]

// // 第i项选a的话,余数加上(n-1)*a = j,所以i-1的余数是(j-(n-1)*a)%n

// // 第i项选b的话,余数减去(n-1)*b = j;所以i-1的余数是(j+(n-1)*b;)%n

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

// // 的余数。

// // f[i][j] = (f[i-1][(j-(n-1)*a)%n] + f[i-1][(j+(n-1)*b)%n])%mod;

// // c++中的负数取模会得到负数,但数学中的负数取模是应该得到正数的,要写上一个取模函数把负数取模补正


// 检查范围

// 1≤n≤1000

// ,

// −109≤s≤109

// ,

// 1≤a,b≤106

// 取模是1e8的,没有*10操作,不可能爆int


目录
相关文章
|
开发工具
推荐几款typora替代品
MarkText Typedown Atom
|
3月前
|
人工智能 前端开发 测试技术
Kimi K2 模型更新,带来更强的代码能力、更快的 API
今天,Kimi K2 模型的最新版本 0905 开源发布,进一步提升其在真实编程任务中的表现
920 0
|
9月前
|
移动开发 前端开发 开发者
React 音频播放控制组件 Audio Controls
本文介绍了如何使用React构建音频播放控制组件,涵盖HTML5 `&lt;audio&gt;`标签和React组件化思想的基础知识。针对常见问题如播放状态管理、进度条更新不准确及跨浏览器兼容性,提供了详细的解决方案和代码示例。同时,还总结了易错点及避免方法,如确保音频加载完成再操作、处理音频错误等,帮助开发者实现稳定且功能强大的音频播放器。
390 11
|
数据采集 SQL 安全
2024年护网行动全国各地面试题汇总(5)
2024年护网行动全国各地面试题汇总(5)
|
Unix Linux
Linux | Rsync 命令:16 个实际示例(下)
Linux | Rsync 命令:16 个实际示例(下)
Linux | Rsync 命令:16 个实际示例(下)
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
|
SQL 人工智能 安全
网络安全漏洞与防御策略
在数字化时代,网络安全成为维护信息安全的关键防线。本文将探讨网络安全中常见的漏洞类型、加密技术的应用以及提升安全意识的重要性。通过分析具体案例,我们将了解如何识别和防御网络威胁,并强调个人与企业在构建网络安全体系中的作用。
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的健身管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的健身管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
109 0
|
传感器 算法
STM32智能小车循迹教程
STM32智能小车循迹教程
1802 0