概率与期望——P1291 [SHOI2002]百事世界杯之旅

传送门

P1291 [SHOI2002]百事世界杯之旅

题目分析

我们可以设 f ( n , k ) f(n,k) f(n,k)表示共 n n n个名字,剩下 k k k个名字未收集到,需购买饮料的平均次数。
则有:
f ( n , k ) = ( n − k ) f ( n , k ) n + k f ( n , k − 1 ) n + 1 f(n,k)=\frac {(n-k)f(n,k)}{n}+ \frac{kf(n,k-1)}{n}+1 f(n,k)=n(nk)f(n,k)+nkf(n,k1)+1经过移项整理,会得到递推式: f ( n , k ) = f ( n , k − 1 ) + n k f(n,k)=f(n,k-1)+\frac {n}{k} f(n,k)=f(n,k1)+kn
根据递推式可得: f ( n , 0 ) = n ∑ k = 1 n 1 k f(n,0)=n\sum_{k=1}^{n}\frac{1}{k} f(n,0)=nk=1nk1
同时注意约分和输出即可

Code

#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;

inline int read()
{
	int x = 0, f = 1; char c = getchar();
	while (c > '9' || c < '0') {if (c == '-') f = -1; c = getchar();}
	while (c >= '0' && c <='9') {x = x * 10 + c - '0'; c = getchar();}
	return f * x; 
}

int n;
ll p,q=1,g;

ll gcd(ll a, ll b)
{
	return b ? gcd(b, a % b) : a;
}

int wei(ll x)//计算位数
{
	int res = 0;
	for (; x; x /= 10) ++res;
	return res;
}

int main()
{
	n = read();
	for (int i = 1; i <= n; ++i)
	{
		p = p * i + q * n; q *= i;//递推
		g = gcd(p, q);
		p /= g, q /= g;//过程约分
	}g = p / q, p %= q;
	if (!p) printf("%lld\n", g);
	else
	{
		for (int i = wei(g); i >= 1; --i) putchar(' ');
		printf("%lld\n", p);
		if(g) printf("%lld",g);
		for (int i = wei(q); i >= 1; --i) putchar('-');
		printf("\n");
		for (int i = wei(g); i >= 1; --i) putchar(' ');
		printf("%lld\n",q);
	}
	return 0;
} 

总结与反思

  1. 当数据较大时,要每一步进行模数、约分等操作,同时注意要先除后乘,防止爆数据结构
  2. 期望 d p dp dp的题目很有趣,码量并不大,但要熟练掌握期望 d p dp dp方程式的推法
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值