输入输入第一行一个数n(1<=n<=100),表示题目的个数。第二行n个整数,p1,p2,...,pn。表示小明有pi%的概率做对第i题。(0<=pi<=100)
输出小明通过考试的概率,最后结果四舍五入,保留小数点后五位。
时间限制C/C++语言:1000MS其它语言:3000MS
内存限制C/C++语言:65536KB其它语言:589824KB
#include <iostream> #include <math.h>#include <algorithm>#include <vector>int main() {int N;std::cin >> N;std::vector<int> Parr(N+1);Parr[0] = 0;for(int i=1; i<=N; i++){std::cin >> Parr[i];} // 状态:dp[i][j]代表共有i个题目,通过j个题目的概率 // 方程:dp[i][j] = P[j] * dp[i-1][j-1] + (1-P[j]) * dp[i-1][j] // 即i个题目通过j个题目的概率,可以表示为,如果第j个题目通过了,那么前i-1个题目中我通过了j-1个,所以这部分概率为 P[j] * dp[i-1][j-1]// 如果第j个题目没有通过,那么前i-1个题目中我通过了j个,所以这部分概率为(1 - P[j]) * dp[i-1][j]// 初始化: dp[0][0] = 1, dp[0][1] = 0; std::vector<std::vector<double>> dp(N+1, std::vector<double>(N+1, 0));dp[0][0] = 1;//这一句很重要dp[0][1] = 0;for(int i=1; i<=N; i++){dp[i][0] = (1 - double(Parr[i]) / 100) * dp[i-1][0];for(int j=1; j<=i; j++){dp[i][j] = double(Parr[i]) / 100 * dp[i-1][j-1] + (1 - double(Parr[i]) / 100) * dp[i-1][j];} }//最少要通过 min 个题目 int min = ceil(N * 0.6);double ans = 0.0;//最后的结果即 dp[N][min] + dp[N][min + 1] + ... + dp[N][N] // 即 N个题目中通过min个, 通过min+1个 。。。 通过N个的概率相加 for(int i=min; i<=N; i++){ans += dp[N][i];} printf("%.5f", ans);}//当然这道题目还可以优化,即使用滚动数组代替二维数组,此时空间复杂度由O(n^2)变为O(n) //代码如下/*#include <iostream> #include <math.h>#include <algorithm>#include <vector>int main() {int N;std::cin >> N;std::vector<int> Parr(N+1);Parr[0] = 0;for(int i=1; i<=N; i++){std::cin >> Parr[i];} std::vector<double> dp(N+1, 0);dp[0] = 1;for(int i=1; i<=N; i++){dp[0] = (1 - double(Parr[i]) / 100) * dp[0];for(int j=i; j>=1; j--){dp[j] = double(Parr[i]) / 100 * dp[j-1] + (1 - double(Parr[i]) / 100) * dp[j];} }int min = ceil(N * 0.6);double ans = 0.0;for(int i=min; i<=N; i++){ans += dp[i];} printf("%.5f", ans);} */
2 分堆A(京东2017实习生真题) 2
题目描述
小明得到了n个石头,他想把这些石头分成若干堆,每堆至少有一个石头。他把这些石堆排在一条直线上,他希望任意相邻两堆的石头数都不一样。小明最后的得分为石头数大于等于k的石堆数,问他最多能得多少分。
严格地,小明把n个石头分成了m堆,每堆个数依次为a1,a2.....,am。要求满足:
1、ai≥1(1≤i≤m)
2、ai≠ai+1(1≤i<m)
3、a1+a2+...+am=n
小明想知道中大于等于的数最多能有多少个?
时间限制C/C++语言:1000MS其它语言:3000MS
内存限制C/C++语言:65536KB其它语言:589824