luogu1291 百事世界杯之旅 题解

分析

有一个显然的结论:设当前已经获得的名字个数为 \(k\),那么再获得其他名字的概率为 \(\frac{n-k}{n}\)。也就是说,平均买 \(n\) 次有 \(n-k\) 个其他的名字,那么再获得一个平均次数为 \(\frac{n}{n-k}\)

感性理解一下

事实上有这个定理,对于事件 \(A\),有 \(P(A)=p\),那么发生 \(A\) 的期望次数 \(E(A)= \frac{1}{p}\)

回到题目,就是要求 \(\sum_{i=1}^n \frac{n}{i}\)。要输出为分数形式,那么分别计算分子与分母,最后判断输出就行了。细节见代码。

CODE

#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
int n;
ll p, q, r;
ll gcd(ll x,ll y) { return y? gcd(y,x%y):x; }
int main() {
	scanf("%d",&n);
	p=0, q=1;
    // p是分子,q是分母
	for(int i=1;i<=n;++i) {
		p=p*i+q*n, q*=i;
        // 模拟分数加法,可以自己验证一下
		ll d=gcd(p,q);
        // 及时化简分子分母
		p/=d, q/=d;
	}
	r=p/q, p%=q;
    // r是整数部分,p要去掉r*q这部分
	if(!p) printf("%lld\n",r);
    // 分子是0,表示r是整数
	else {
		int d=log10(r)+1;
        // 整数x的位数=log10(x)+1
		while(d--) printf(" ");
		printf("%lld\n",p);
		d=log10(q)+1;
		if(r) printf("%lld",r);
        // 如果有带分数整数部分,就输出
		while(d--) printf("-"); puts("");
		d=log10(r)+1;
		while(d--) printf(" ");
		printf("%lld\n",q);
	}
}

luogu1291 百事世界杯之旅 题解
https://yozora0908.github.io/2022/lg1291-solution/
作者
yozora0908
发布于
2022年2月19日
许可协议