简介:
买彩票
分析:
假设我们现在手里已经有了k图案,令s=k/n,拿一个新的图案需要t次的概率:s^(t-1)*(1-s)
也就是说,平均拿n/(n-k)次就可以多收集一个图案
所以答案就是:
问题就解决了。。。吗
题目要求输出分数,所以我们需要通分一下:
我们只要分别计算出分子和分母就可以了(不要忘了约分)
问题就再次解决了。。。吗
33!>2*10^32
这是ull都无法承受的,那我们只能向高精度低头了吗
不!!!
实际上,计算的过程中,我发现分子分母不一定互质,如果我们等到最后再约分,显然会GG
那我们可以边乘边约分吗?
也不行,因为我们的分析是连加操作,不能在过程中进行约分
实际上我们这要先预处理出1~n的lcm(而不是直接计算n!)
这样就可以把数量级减少一半(lcm[33]<1.5*10^14)
我们直接把lcm[n]当做n!来用,就可以完美解决问题
问题终于彻底解决了
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll unsigned long long
using namespace std;
ll n,lcm[40];
ll GCD(ll a,ll b)
{
ll r=a%b;
while (r)
{
a=b;b=r;
r=a%b;
}
return b;
}
ll LCM(ll a,ll b)
{
return a/GCD(a,b)*b; //先除再乘,防止爆ull
}
int get(ll x)
{
int t=0;
while (x)
{
t++;
x/=10;
}
return t;
}
int main()
{
lcm[1]=1;
for (int i=2;i<=33;i++) lcm[i]=LCM(lcm[i-1],i);
while (scanf("%llu",&n)!=EOF)
{
ll M=lcm[n];
ll m=0;
for (int i=1;i<=n;i++) m+=lcm[n]/i;
m*=n;
ll a=GCD(m,M);
m/=a; M/=a;
ll d=m/M;
m%=M;
if (m){
int r1=get(d)+1;
int r2=get(M);
for (int i=1;i<=r1;i++) printf(" "); printf("%llu\n",m);
printf("%llu ",d); for (int i=1;i<=r2;i++) printf("-"); printf("\n");
for (int i=1;i<=r1;i++) printf(" "); printf("%llu\n",M);
}
else{
printf("%llu\n",d);
}
}
return 0;
}