擅长解密的小红同学
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网题目描述
小红来到了一个机关前,准备破解机关的密码门。
已知机关的密码是一串数字('0'~'9')。小红经过不懈的努力,终于破解了每个数字出现的次数。但她并不知道每个数字出现的先后次序。
于是她只能随机来尝试破解密码。不过这个机关有个特点:每当小红输入一次尝试之后,密码都会重置。不过每个数字出现的次数不变。
小红想知道自己尝试次数的期望是多少?
输入描述:
一行共 10 个非负整数 aia_iai ,分别代表 '0'~'9' 每个数字的出现次数。
0≤ai≤10^6 ,且保证所有 aia_iai 不会全为0。
输出描述:
小红尝试次数的期望,对 10^9 + 7取模。
可以证明,该期望一定为有理数。如果该期望为分数,请输出分数取模的值。
分数取模的定义: x/y mod p=a ,等价于 a∗y mod p=x
示例1
输入
0 2 0 0 0 0 0 0 0 0
输出
1
说明
已知数字 1 出现了 2 次,那么密码只有可能是 "11" ,小红只需要一次输入即可破解。
示例2
输入
1 1 0 0 0 0 0 0 0 0
输出
2
说明
已知数字 0 出现了 1 次,数字 1 出现了 1 次,那么密码可能是 "01" 或者 "10" 。由于密码可能会重置,因此小红每次尝试的成功概率为 12 \frac{1}{2} 21 。
尝试次数的期望为 12+2∗14+3∗18+4∗116...=2 \frac{1}{2} + 2 * \frac{1}{4} + 3 * \frac{1}{8} + 4 * \frac{1}{16} ... = 2 21+2∗41+3∗81+4∗161...=2
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll mo = 1e9 + 7;
const int N = 1e7 + 1;
ll a[11];
ll f[N],inv[N];
ll qpow(ll a, ll b)
{
ll ans = 1;
while (b > 0)
{
if (b & 1)
ans = ans * a % mo;
a = a * a % mo;
b >>= 1;
}
return ans;
}
int main()
{
int sum=0;
for (int i = 0; i <= 9; i++)
{
cin >> a[i];
sum += a[i];
}
f[0] = 1;
for (int i = 1; i <= sum; ++i) f[i] = f[i - 1] * i % mo;
inv[sum] = qpow(f[sum], mo - 2);
for (int i = sum - 1; i > 0; --i) inv[i] = inv[i + 1] * (i + 1) % mo;
ll ans =f[sum];
for (int i = 0; i <= 9; i++)
{
if (a[i])
{
ans = ans * inv[a[i]] % mo;
}
}
cout << ans;
}
increment of coins
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
背包有三种硬币,AAA 枚金币,BBB 枚银币, CCC 枚铜币。
在某一种硬币有100枚,之前重复以下操作:
随机从背包选一枚硬币。(每一个硬币被取到的概率相等。)然后放一枚一样的硬币进去。
请计算操作次数的期望值。输入描述:
输入三个整数A,B,C。
数据范围:
0≤A,B,C≤990 \le A,B,C \le 990≤A,B,C≤99
A+B+C≥1A+B+C \ge 1A+B+C≥1
输出描述:
请输出操作次数的期望值。你的输出与正确答案的误差应该最多10−610^{-6}10−6。示例1
输入
复制99 99 99
输出
复制1.000000000
说明
在第一次操作,选择任何1枚硬币,背包里都是100枚硬币
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
double dp[105][105][105];
int main()
{
int a,b,c;
cin>>a>>b>>c;
for(int i=100;i>=0;i--)
{
for(int j=100;j>=0;j--)
{
for(int k=100;k>=0;k--)
{
if(i==100||j==100||k==100)dp[i][j][k]=0;
else
if(i+j+k!=0){
dp[i][j][k]+=(double)i/(i+j+k)*(dp[i+1][j][k]+1);
dp[i][j][k]+=(double)j/(i+j+k)*(dp[i][j+1][k]+1);
dp[i][j][k]+=(double)k/(i+j+k)*(dp[i][j][k+1]+1);
}
}
}
}
cout<<fixed<<setprecision(8)<<dp[a][b][c]<<endl;
}
Little Pony and Expected Maximum
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
一个骰子有 mmm 面,第一个面有一个点,第二面有两个点,以此类推。Twilight Sparkle 确定投掷骰子时,每一面都是等概率出现的,即每面出现的概率为 1m\frac{1}{m}m1。并且她知道每次投掷的结果是独立的。帮助她计算投掷 nnn 次骰子所能获得最大值的期望。
输入描述:
第一行包含两个整数 m,n(1≤m,n≤105)m,n(1\leq m,n\leq 10^5)m,n(1≤m,n≤105)。输出描述:
输出一个实数表示期望最大值。当你的输出和答案的相对误差或者绝对误差不超过 10−410^{-4}10−4 时被视为正确。示例1
输入
复制6 1
输出
复制3.500000000000
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
//const ll mo = 1e9 + 7;
const int N = 1e7 + 1;
double f[N];
double qpow(double a, ll b)
{
double ans = 1.0;
while (b > 0)
{
if (b & 1)
ans = ans * a;
a = a * a;
b >>= 1;
}
return ans;
}
int main()
{
int m, n;
cin >> m >> n;
double ans = 0;
for (int i = 1; i <= m; i++)
{
f[i] = qpow((double)i / m, n);
}
for (int i = 1; i <= m; i++)
{
ans += (double)i * (f[i] - f[i - 1]);
}
cout << ans;
}
Messages
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网题目描述
Monocarp 是 nnn 个学生的导师,他通过发送消息和学生练习。现在有很多条消息,Monocarp 希望第 iii 个学生能够阅读编号为 mim_imi 的消息。但是学生只会阅读置顶的消息,因此他需要把一些消息置顶。
学生 iii 有一个属性 kik_iki。如果 Monocarp 置顶了 ttt 条消息,若 t≤kit\le k_it≤ki,该学生会阅读所有置顶消息;否则,该学生会从置顶的 ttt 条消息中随机选 kik_iki 条阅读。
你需要求出在使得第 iii 名学生阅读到编号为 mim_imi 的消息的 iii 的数量的期望值最大时,Monocarp 应该置顶哪些消息。如果有多个答案,输出任意一种。输入描述:
第一行一个整数 n (1≤n≤2×105)n\ (1\le n\le 2\times 10^5)n (1≤n≤2×105)。 接下来 nnn 行,第 iii 行有两个整数 mi,ki (1≤mi≤2×105,1≤ki≤20)m_i,k_i\ (1\le m_i\le 2\times 10^5,1\le k_i\le 20)mi,ki (1≤mi≤2×105,1≤ki≤20)。输出描述:
第一行一个整数 t(1≤t≤2⋅105)t(1\leq t\leq 2\cdot10^5)t(1≤t≤2⋅105),表示你置顶的消息条数。 第二行包含 ttt 个不同的整数 c1,c2,…,ct(1≤ci≤2⋅105)c_1,c_2,\dots,c_t (1\leq c_i\leq 2\cdot10^5)c1,c2,…,ct(1≤ci≤2⋅105),表示你置顶的消息编号。示例1
输入
3 10 1 10 2 5 2输出
2
5 10
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
//const ll mo = 1e9 + 7;
const int N = 2e5 + 5;
int m[N], k[N];
bool check(pair<int, int> a, pair<int, int> b)
{
return a.first * b.second > a.second * b.first;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> m[i] >> k[i];
}
vector<int>cert;
pair<int, int >ans = {0, 1};
for (int i = 1; i <= 20; i++)
{
vector<int> s(N);
for (int j = 0; j < n; j++)
{
s[m[j]] += min(i, k[j]);
}
vector<pair<int, int>>a;
for (int j = 0; j < N; j++)
{
a.push_back(make_pair(s[j], j));
}
sort(a.rbegin(), a.rend());
pair<int, int> cur_ans = {0, i};
vector<int>cur_cert;
for (int j = 0; j < i; j++)
{
cur_ans.first += a[j].first;
cur_cert.push_back(a[j].second);
}
if (check(cur_ans, ans))
{
ans = cur_ans;
cert = cur_cert;
}
}
cout << cert.size() << endl;
for (auto x : cert)
cout << x << " ";
cout << endl;
}
/*
x = 读到自己需要的消息的学生数量=x1+x2+x3+x4+...+xn
期望的可加性
Ez=Ex+Ey (z=x+y)
Ex=Ex1+Ex2+Ex3+...+Exn
xi=1表示第i个学生读到mi
E[xi]=1*P(xi==1)+0*P(xi==0)= P(xi==1)第i个学生读到mi
而 P(xi==1)=|0 ,mi !∈{m1...mt}
|1 ,mi∈{m1...mt} && t<=ki
|ki/t ,t>ki
接下来要找一组 {m1...mt} , t 使得期望E[x]最大
*/