(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
Catalog
Problem:Portal传送门
原题目描述在最下面。
(n-1)!天可以抽一次卡,共有n张卡,问抽到n张卡的期望天数是多少。
n≤3000
n
≤
3000
Solution:
期望天数 = 期望次数 * (n-1)!
考虑当我们已经抽到了k张卡,我们还需要抽多少次才能抽到k+1张卡的期望?
答案是:
nn−k
n
n
−
k
。抽到新卡概率是:
n−kn
n
−
k
n
对于事件A有:
E(A)=1P(A)
E
(
A
)
=
1
P
(
A
)
所以:期望次数:
∑n−1i=0nn−i
∑
i
=
0
n
−
1
n
n
−
i
.
ans=n×(n−1)!×∑ni=11i
a
n
s
=
n
×
(
n
−
1
)
!
×
∑
i
=
1
n
1
i
到这里这个题的难度就在于3000的阶乘爆longlong了,爆__int128了。要么敲大整数模板要么用Java。我用Java写的,不过这里有一个很好的大整数模板:here。
虽然调和级数是浮点数,但是在乘了
n∗(n−1)!
n
∗
(
n
−
1
)
!
后它肯定是整数啦。
关于求大数调和级数的方法:here
AC_Code:
import java.io.*;
import java.math.*;
import java.util.*;
import java.math.BigInteger;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Scanner;
public class Main{
static PrintStream putOut = System.out;
static BigInteger pw[] = new BigInteger[3005];
static BigInteger ans[] = new BigInteger[100005];
static double c=0.57721566490153286060651209;
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
pw[0] = BigInteger.valueOf(1);pw[1]=pw[0];
for(int i=2;i<=3000;++i){
pw[i] = pw[i-1].multiply(BigInteger.valueOf(i));
}
int tim = cin.nextInt();
for(int t=0;t<tim;++t){
int n = cin.nextInt();
BigInteger tmp = new BigInteger("0");
tmp = BigInteger.valueOf(n);
tmp = tmp.multiply(pw[n-1]);
BigInteger ans = BigInteger.valueOf(1),hh=tmp;
tmp = BigInteger.valueOf(0);
for(int i=1;i<=n;++i){
tmp = tmp.add(hh.divide(BigInteger.valueOf(i)));
}
putOut.println(tmp+".0");
}
}
}