(排列,选择类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


目录
相关文章
|
7月前
|
移动开发 前端开发 开发者
React 音频播放控制组件 Audio Controls
本文介绍了如何使用React构建音频播放控制组件,涵盖HTML5 `&lt;audio&gt;`标签和React组件化思想的基础知识。针对常见问题如播放状态管理、进度条更新不准确及跨浏览器兼容性,提供了详细的解决方案和代码示例。同时,还总结了易错点及避免方法,如确保音频加载完成再操作、处理音频错误等,帮助开发者实现稳定且功能强大的音频播放器。
313 11
|
12月前
|
Unix Linux
Linux | Rsync 命令:16 个实际示例(下)
Linux | Rsync 命令:16 个实际示例(下)
Linux | Rsync 命令:16 个实际示例(下)
|
存储 C++ 索引
C++ 序列容器Vector各种方法实现原理(带你从本质理解Vector容器)(上)
C++ 序列容器Vector各种方法实现原理(带你从本质理解Vector容器)
input输入框输入只能输入数字、字母等组合的正则表达式
input输入框输入只能输入数字、字母等组合的正则表达式
1189 0
|
Java Go 容器
【Java每日一题,容器+思维】csp202012-2 期末预测之最佳阈值
【Java每日一题,容器+思维】csp202012-2 期末预测之最佳阈值
DHL
|
Java API Android开发
EventBus3.1用法详解
EventBus是Android和Java的发布/订阅事件总线。从EventBus3.1开始支持普通Java(非android)项目。GitHub的地址
DHL
318 0
EventBus3.1用法详解
|
XML 数据格式
SpringMVC - 数据绑定(Xml、@InitBinder、Set、嵌套对象、多个对象)(二)
SpringMVC - 数据绑定(Xml、@InitBinder、Set、嵌套对象、多个对象)(二)
254 0
|
Java 前端开发 JavaScript
velocity的一些用法
velocity模板其实就是java不分语法的翻译,用到的属性还是java的方法,get,set,等 1.截取部分字段substring 1 原始字符串:$!ag.tagValue,也许很长,前端页面展示时需要截取字符串。
1116 0
|
Java
The superclass &quot;javax.servlet.http.HttpServlet&quot; was not found on the Java Build Path
<p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> 转自:<a target="_blank" href="http://blog.csdn.net/testcs_dn/article/details/36455669">http://blog.csdn.net/test
2284 0