[Luogu1291][SHOI2002]百事世界杯之旅
题目描述
“……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”
你关上电视,心想:假设有n个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?
输入输出格式
输入格式:整数n(2≤n≤33),表示不同球星名字的个数。
输出格式:输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为(复制到记事本): 5 $\frac{3}{20}$ 第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的为数。分子和分母的首位都与第一个减号对齐。
分数必须是不可约的。
输入输出样例
2
3
我们设f[i]为已经收集了i名球星,要收集到n名的期望步数;
显然 $f[i]= \frac{i}{n} f[i]+ \frac{n-i}{n} f[i+1]+1$
化简得: $f[i]= \frac{n}{n-i} +f[i+1]$
把i=i-1带入,$f[i-1]= \frac{n}{n-i+1} +f[i]$
所以答案就是$ \sum_{i=1}^{n} \frac{n}{n-i+1}$
然后就简单了,我们设a为分子,b为分母,然后模拟一下...
一定要全开long long,然后除法记得加括号,要不然会在某个地方爆long long。
我就是在这卡这么久...加上括号就过了...
对了这输出太恶心了...丧心病狂
吐槽:话说2002真是让人激动的一年...至少对于曾经辉煌过的国足来说,自此,再没看到国足崛起。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define int long long #define gc getchar() inline int read(){ int res=0;char ch=gc; while(!isdigit(ch))ch=gc; while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=gc;} return res; } #undef gc int n; int a, b; int gcd(int x, int y){return y==0?x:gcd(y,x%y);} int chai(int x) { int num = x; int cnt = 0; while(num) { cnt++, num/=10; } return cnt; } signed main() { n = read(); a = 3, b = 2; for (int i = 3 ; i <= n ; i ++) { int g1 = gcd(i, b); int lcm = i * b / g1; a = a * (lcm / b) + lcm / i; int g2 = gcd(a, lcm); a /= g2, b = lcm / g2; // printf("%lld %lld\n", a, b); } a *= n; if (a % b == 0) return printf("%lld\n", a / b), 0; int g1 = gcd(a, b); a /= g1, b /= g1; int f; f = a / b; a %= b; int ff = chai(f); int fff = max(chai(a), chai(b)); for (int i = 1 ; i <= ff ; i ++) printf(" "); printf("%lld\n", a % b); if (f >= 1)printf("%lld", f); for (int i = 1 ; i <= fff ; i ++) printf("-"); printf("\n"); for (int i = 1 ; i <= ff ; i ++) printf(" "); printf("%lld", b); return 0; }
$\sum_{age=16}^{18} hardworking = success$