学习C++从娃娃抓起!记录下在学而思小猴编程学习过程中的题目,记录每一个瞬间。侵权即删,谢谢支持!
附上汇总贴:小猴编程C++ | 汇总-CSDN博客
【题目描述】
经过了上次的飞盘比赛,约翰想要重新组一只飞盘队,他打算从他家的
n
n
n头奶牛中选出一支队伍。
每只奶牛的能力为整数,第
i
i
i头奶牛的能力为
R
i
R_i
Ri。飞盘队的队员数量不能少于
1
1
1、大于
n
n
n。一支队伍的总能力就是所有队员能力的总和。
约翰想要他的队伍能力值总和越大越好。但是他还是比较迷信,他的幸运数字是
F
F
F,所以他要求队伍的总能力必须是
F
F
F的倍数。
请帮他算一下,符合这个要求的队伍的能力值最大是多少?并且达成最大能力值的方法数有多少种?
【输入】
第
1
1
1行:两个用空格分开的整数:
n
n
n和
F
F
F。
第
2
2
2行:
n
n
n个整数
R
1
,
R
2
,
…
,
R
n
R_1,R_2,\dots,R_n
R1,R2,…,Rn,
R
i
R_i
Ri表示第
i
i
i头奶牛的能力。
【输出】
第
1
1
1行:
1
1
1个整数,表示在总能力为
F
F
F的倍数的前提下,可以达到的最大能力值。
第
2
2
2行:
1
1
1个整数,表示达到最大能力值的方案数。
【输入样例】
4 5
1 2 2 8
【输出样例】
10
2
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, F;
int dp[105][1005], f[105][1005], r[105];
signed main()
{
cin >> n >> F;
for (int i=1; i<=n; i++) { // 输入每头奶牛的能力
cin >> r[i];
}
memset(dp, -0x3f, sizeof(dp)); // dp初始化为负无穷,表示不可能的情况
dp[0][0] = 0,f[0][0] = 1; // dp首值为0,f首值为1
for (int i=1; i<=n; i++) { // 遍历n头奶牛
for (int j=0; j<=F-1; j++) { // 遍历F的余数范围
int t1 = dp[i-1][j]; // 不取的情况
int t2 = dp[i-1][((j-r[i])%F+F)%F] + r[i]; // 取的情况
dp[i][j] = max(t1, t2); // 两者最大值
if (t1>t2) { // 不取时
f[i][j] = f[i-1][j]; // 继承不取的方法数
} else if (t1<t2) { // 取的时候
f[i][j] = f[i-1][((j-r[i])%F+F)%F]; // 继承取的方法数
} else { // 相等时,两者要相加
f[i][j] = f[i-1][j] + f[i-1][((j-r[i])%F+F)%F];
}
}
}
cout << dp[n][0] << endl; // 输出第n头奶牛的,模F为0的总和
cout << f[n][0] << endl; // 输出第n头奶牛的,模F为0的方法数
return 0;
}
【运行结果】
4 5
1 2 2 8
1 1 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0
1 1 2 2 1 0 0 0 0 0 0
2 2 1 1 1 0 0 0 0 0 0
10
2