最新文章
这里会显示最新的几篇文章摘要。
记录生活,分享知识,与你一起成长。
这里会显示最新的几篇文章摘要。
Farmer Han开始玩飞盘之后,YDS也打算让奶牛们享受飞盘的乐趣.他要组建一只奶牛飞盘队.他的N(1≤N≤2000)只奶牛,每只奶牛有一个飞盘水准指数Ri(1≤Ri≤100000).YDS要选出1只或多于1只奶牛来参加他的飞盘队.由于YDS的幸运数字是F(1≤F≤1000),他希望所有奶牛的飞盘水准指数之和是幸运数字的倍数.
帮YDS算算一共有多少种组队方式.组队方式数模10^8取余的结果.
第1行输入N和F,之后N行输入Ri
组队方式数模10^8取余的结果
4 5 12 8 2
3
dp[i][j]为前i头奶牛,得到飞盘准指数为j的方案数dp[0][0] == 1 dp[i-1][(j-v[i]+f)%f],因为题目要求的是余数,因此不必考虑j >= v[i]的条件状态定义:
通常我们用 dp[i][r] 表示前 i 只奶牛构成的子集(通常包括空集)的方案数,其中这些奶牛的飞盘水准指数之和对 ( F ) 取模后等于 ( r )。
下标范围:
因为模 ( F ) 的余数只可能在 0 到 ( F-1 ),所以 dp[i] 的第二维应该有 ( F ) 个位置,而不是 1005 个位置。如果题目中 ( F ) 最大为 1000,定义 dp[2005][1005] 是可以的,但在状态转移时,下标应该在 0 到 ( F-1 ) 范围内。
但你的循环写的是
for (int j = 1; j <= f; ++j)
这样就把下标范围写成了 1 到 ( F ),而下标 ( F ) 对应的余数其实应该是 0(因为 ( F \mod F = 0 )),这会导致混淆甚至可能出错。
正确的状态转移应该是:
当考虑第 ( i ) 只奶牛(其水准指数经过取模后为 ( v[i] ))时,对于任意余数 ( r ) 应有:
[
dp[i][r] = dp[i-1][r] + dp[i-1][(r - v[i] + F) % F]
]
其中:
你写的代码中用了条件判断:
if(j >= v[i])
dp[i][j] += dp[i-1][j] + dp[i-1][(j-v[i])];
else
dp[i][j] += dp[i-1][j];
这种写法只适用于普通的区间和问题,但对于模运算必须无条件地进行模的调整,也就是说,无论 ( j \ge v[i] ) 与否,都应使用公式:
dp[i][j] = dp[i-1][j] + dp[i-1][(j - v[i] + f) % f];
这样就可以保证下标不会出现负值,并且保持余数在 ( 0 ) 到 ( f-1 ) 范围内。
dp[0][0] = 1;
表示“空集”对应的方案数为 1。dp[i][0] = 1;
这种处理可能导致后续转移时多次重复计入“空集”的方案。下面给出一个修改后的参考代码,解决上述问题:
#include <iostream>
#include <cstring>
using namespace std;
const int MOD = 100000000; // 题目要求模 10^8
int v[2005];
int dp[2005][1005]; // dp[i][r] 表示前 i 只奶牛构成的子集,其和模 f 为 r 的方案数
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
memset(dp, 0, sizeof(dp)); // 初始化 dp 数组
int n, f;
cin >> n >> f;
for (int i = 1; i <= n; ++i) {
cin >> v[i];
v[i] %= f; // 只需要关心模 f 的值
}
// 初始状态:空集方案数为 1
dp[0][0] = 1;
// 状态转移
for (int i = 1; i <= n; ++i) {
for (int r = 0; r < f; ++r) {
// 不选第 i 只奶牛:状态保持不变
dp[i][r] = (dp[i][r] + dp[i-1][r]) % MOD;
// 选第 i 只奶牛:更新余数
int prev = (r - v[i] + f) % f;
dp[i][r] = (dp[i][r] + dp[i-1][prev]) % MOD;
}
}
// dp[n][0] 包含了空集的方案数,所以答案应为 dp[n][0] - 1
int ans = dp[n][0] - 1;
if (ans < 0) ans += MOD;
cout << ans << "\n";
return 0;
}
memset(dp, 0, sizeof(dp)); 替换 mem(dp);0 到 f-1 内,而不是 1 到 f。这样修改后,你的代码就可以正确解决题目要求了。