拼多多9.1笔试第三道--骰子期望(cpp实现)
如题,以下给出我的cpp代码,各位牛友看看我的思路怎么样哈。
ps:代码已验证过,头文件等放到了帖子最后。。。
// 计算当骰子最大值为t时的所有方案数
// greatCnt为骰子最大点数大于等于t的骰子总数
// lesss为最大点数小于t的骰子集合,存放的是其最大点数
long long cal(int t, int greaterCnt, vector<int> &lesss);
long long cnk(int n, int k); // 计算组合数cnk,即从n个颜色相同的球中取k个球的方案数
int main() {
int n;
cin >> n;
vector<int> cnt(n); // 存放每个骰子的最大点数
int Max = INT_MIN;
double div = 1.0;
for (int i = 0; i < n; i++) {
cin >> cnt[i];
Max = max(Max, cnt[i]);
div *= cnt[i]; // 所有可能的方案数
}
vector<long long> record(Max + 1); // record[i]--输出为i时 对应的方案总数
vector<int> greaters(Max + 1); // greaters[i]--最大点数值可大于等于i的骰子总数
vector<vector<int>> lesss(Max + 1); // lesss[i]--最大点数值小于i的骰子集合,存放的是骰子的最大点数
for (int i = 0; i < n; i++) {
for (int j = 1; j <= cnt[i]; j++) {
greaters[j]++;
}
for (int j = cnt[i] + 1; j <= Max; j++) {
lesss[j].push_back(cnt[i]);
}
}
for (int i = 1; i <= Max; i++) {
record[i] = cal(i, greaters[i], lesss[i]);
}
long long total = 0;
for (int i = 1; i <= Max; i++) {
total += (record[i] * i); // 输出点数 * 方案数 并求和
}
double ans = total / div; // 除以总的方案数,计算期望
cout << fixed << setprecision(2);
cout << ans << endl;
system("pause");
return 0;
}
long long cal(int t, int greaterCnt, vector<int> &lesss) {
long long cnt1 = 1; // 小于t的骰子可组成的方案总数
for (int i = 0; i < lesss.size(); i++) {
cnt1 *= lesss[i];
}
long long cnt2 = 0;
for (int i = 1; i <= greaterCnt; i++) {
// 从greaterCnt个骰子中选i个骰子,使其点数为t,则剩下的greaterCnt - i个骰子,每个点数可取值为1 ~ t - 1
cnt2 += (cnk(greaterCnt, i) * pow(t - 1, greaterCnt - i));
}
return cnt1 * cnt2;
}
long long cnk(int n, int k) {
if (n == k || !k) {
return 1;
}
return cnk(n - 1, k) + cnk(n - 1, k - 1);
}
#include <iostream>
#include <vector>
#include <algorithm>
// greatCnt为骰子最大点数大于等于t的骰子总数
// lesss为最大点数小于t的骰子集合,存放的是其最大点数
long long cal(int t, int greaterCnt, vector<int> &lesss);
long long cnk(int n, int k); // 计算组合数cnk,即从n个颜色相同的球中取k个球的方案数
int main() {
int n;
cin >> n;
vector<int> cnt(n); // 存放每个骰子的最大点数
int Max = INT_MIN;
double div = 1.0;
for (int i = 0; i < n; i++) {
cin >> cnt[i];
Max = max(Max, cnt[i]);
div *= cnt[i]; // 所有可能的方案数
}
vector<long long> record(Max + 1); // record[i]--输出为i时 对应的方案总数
vector<int> greaters(Max + 1); // greaters[i]--最大点数值可大于等于i的骰子总数
vector<vector<int>> lesss(Max + 1); // lesss[i]--最大点数值小于i的骰子集合,存放的是骰子的最大点数
for (int i = 0; i < n; i++) {
for (int j = 1; j <= cnt[i]; j++) {
greaters[j]++;
}
for (int j = cnt[i] + 1; j <= Max; j++) {
lesss[j].push_back(cnt[i]);
}
}
for (int i = 1; i <= Max; i++) {
record[i] = cal(i, greaters[i], lesss[i]);
}
long long total = 0;
for (int i = 1; i <= Max; i++) {
total += (record[i] * i); // 输出点数 * 方案数 并求和
}
double ans = total / div; // 除以总的方案数,计算期望
cout << fixed << setprecision(2);
cout << ans << endl;
system("pause");
return 0;
}
long long cal(int t, int greaterCnt, vector<int> &lesss) {
long long cnt1 = 1; // 小于t的骰子可组成的方案总数
for (int i = 0; i < lesss.size(); i++) {
cnt1 *= lesss[i];
}
long long cnt2 = 0;
for (int i = 1; i <= greaterCnt; i++) {
// 从greaterCnt个骰子中选i个骰子,使其点数为t,则剩下的greaterCnt - i个骰子,每个点数可取值为1 ~ t - 1
cnt2 += (cnk(greaterCnt, i) * pow(t - 1, greaterCnt - i));
}
return cnt1 * cnt2;
}
long long cnk(int n, int k) {
if (n == k || !k) {
return 1;
}
return cnk(n - 1, k) + cnk(n - 1, k - 1);
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits.h>
#include <iomanip>
using namespace std;
#include <iomanip>
using namespace std;