AcWing 1214. 波动数列(相似于 01背包的 dp)

本文介绍了如何使用动态规划解决一个数学问题,即在模意义下通过加法操作找到特定数位的组合。公式f[i][j]表示在进行n次加法操作后,余数为j的方案数。通过f[i-1][get_mod(j-a*(n-i),n)]和f[i-1][get_mod(j+b*(n-i),n)]求和并取模来更新状态。代码中展示了具体实现,最后输出满足条件的方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目
思路:

公式:
f[i][j] = (f[i - 1][get_mod(j - a * (n - i), n)] + f[i - 1][get_mod(j + b * (n - i), n)]) % MOD;

1号公式:
在这里插入图片描述
一号公式推导过程
在这里插入图片描述

(a % b + b) % b; //得到正余数的公式

分析图:
在这里插入图片描述
在这里插入图片描述

代码:

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, MOD = 100000007;//注意 MOD 复制过来,不要轻易数 0 

int f[N][N];

int get_mod(int a, int b)   // 求a除以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 ++ )//到 n-1 原因:因为前 n-1 确定了话,第 n 项自然就定了(s 是固定的值) 
        for (int j = 0; j < n; j ++ )//余数范围 0~n-1  
            f[i][j] = (f[i - 1][get_mod(j - a * (n - i), n)] + f[i - 1][get_mod(j + b * (n - i), n)]) % MOD;
            //  求余数是 j 的方案数

    cout << f[n - 1][get_mod(s, n)] << endl;//由 一号  公式得到,前 n-1 项的余数为 s%n 时,即为可以得到的方案数。
	//此处必须写成函数调用,来进行取余。s 也有可能是负数 

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值