题目描述
LuckAAA喜欢打炉石,而且是忠实的牧师玩家,他想要收集齐牧师的所有橙卡。 炉石传说目前有n 种牧师橙卡,由于LuckAAA是豹子头零充,又肝不出很多金币,于是他修改了炉石的开包机制,每次开包一定会开出牧师橙卡(所有牧师橙卡中,等概率获得一种,即使已经有了某一种还是可能被抽到,概率均为1/n),但代价是一包只能开出一张。 求LuckAAA每种都收集至少一张时开包数量的期望。
Input
一个整数 n(1<=n<= 1 0 12 ) 10^{12}) 1012)
Output
输出开包数量的期望 若 y 1 y_1 y1是真实值, y 2 y_2 y2是你的答案,当 ∣ y 1 − y 2 ∣ y 1 < = 0.1 \frac {|y_1−y_2|}{y1}<=0.1 y1∣y1−y2∣<=0.1时可以被接受.
Examples
Input
1
Output
1.000000
Input
2
Output
3.000000
Input
3
Output
5.500000
分析
当n很小的时候可以用容斥原理加上状态压缩DP来做。但本题n很大,故通过找规律得到等价于求f(n)=n+n/2+n/3+
.
.
.
.
.
.
......
......+n/n的值。
由于数据大小为
1
0
12
10^{12}
1012,
o
(
n
)
o(n)
o(n)复杂度要超时,考虑
o
(
n
)
o(\sqrt n)
o(n)。
因为允许存在误差,所以可以把x=i到x=n/(n/i)这一部分每一个n/x的值,用n/i代替,这样处理的数据大大减少。以下为AC代码,
代码
#include<bits/stdc++.h>
using namespace std;
int n;
long long ans,d;
int main(){
cin>>n;
for(int i=1;i<=n;i=(n/d)+1){
d=n/i;
ans+=1LL*d*(n/d-i+1);}
cout<<ans;
return 0;
}