H--卡牌游戏:https://www.nowcoder.com/acm/contest/202/H
题意:卡牌的数量为无限,种类为 N ,其中 M 种稀有卡牌,问期望抽多少次能抽到 K 张稀有卡牌(其中普通卡牌可重复抽取,稀有卡牌只能被抽一次)。
解题思路:抽到第一张稀有卡牌的概率为 m/n,抽到第二张稀有卡牌的概率为 m-1/n-1,即抽到 i 张稀有卡牌的概率为 m-i+1/n-i+1,而期望次数则为 1/p。
AC代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int T,n,m,k;
cin>>T;
for(int t = 1; t <= T; t++)
{
cin>>n>>m>>k;
double ans = 0;
for(int i = 0; i < k; i++)
{
ans += n*1.0/m;//获得 i+1 种稀有卡牌的概率为 p = m-i/n-i,期望为 1/p次抽中。
n--;
m--;
}
printf("Case #%d: %.6f\n",t,ans);
}
return 0;
}
F-- 平衡二叉树:https://www.nowcoder.com/acm/contest/202/F
题意:求平衡树(任意一个节点,都满足左右子树的高度差不超过 d )的不平衡度(根节点左右子树节点数之差)的最大值。
解题思路:固定根节点的左子树为满二叉树,求满足条件的右子树最小的节点个数,ans = 左子树的节点个数 - 右子树的最小节点个数。
设 f (n) 为根节点右子树最小的节点个数.
d = 1 时,f(n) = f(n-1) + f(n-2) + 1
d = 2 时,f(n) = f(n-1) + f(n-3) +1
综上,f(n) = f(n-1) + f(n-1-d) + 1
AC 代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
long long a[70],ans;
int n,d;
int main()
{
ios::sync_with_stdio(false);
while(cin>>n>>d)
{
a[0] = a[1] = 0,a[2] = 0;
for(int i = 3; i <= 60; i++)
a[i] = a[i-1] + a[ max(i-d-1, 0) ] + 1;//用 max 函数来代替 if-else 判断 i-d-1 与 0 的大小关系
ans = (1ll<<(n-1)) - 1 - a[ max(n-1-d, 0) ];//k 层满二叉树的节点个数为 pow(2,n-1)-1,左子树的节点为 (pow(2,n-1)-1-1)/2
printf("%lld\n",ans);
}
return 0;
}