假设已经收集了 k k k个图案,那么拿到一个新图案的概率为 n − k n \frac{n-k}{n} nn−k,根据期望的性质,概率为p的期望会在1/p次后发生,那么答案就是 ∑ i = 1 n n n − i \sum_{i=1}^{n}\frac{n}{n-i} ∑i=1nn−in
实际上LRJ在紫书上是手推证明了这个性质(说实话这个证明我看不懂):令 s = k / n s=k/n s=k/n,拿一个新的需要 t t t次的概率为 s t − 1 ( 1 − s ) s^{t-1}(1-s) st−1(1−s),期望为 E E E。因此需要的平均次数为 ( 1 − s ) ( 1 + 2 s + 3 s 2 + 4 s 3 + . . . ) = ( 1 − s ) ∗ E (1-s)(1+2s+3s^2+4s^3+...)=(1-s)*E (1−s)(1+2s+3s2+4s3+...)=(1−s)∗E,即 s ∗ E = ( s + 2 s 2 + 3 s 3 + 4 s 4 + . . . ) = E − ( 1 + 2 s + 3 s 2 + 4 s 3 + . . . ) s*E=(s+2s^2+3s^3+4s^4+...)=E-(1+2s+3s^2+4s^3+...) s∗E=(s+2s2+3s3+4s4+...)=E−(1+2s+3s2+4s3+...),移项得:
( 1 − s ) ∗ E = 1 + s + s 2 + s 2 + . . . (1-s)*E=1+s+s^2+s^2+... (1−s)∗E=1+s+s2+s2+...
根据等比数列的求和公式,得: ( 1 − s ) ∗ E = ( 1 − s t ) / ( 1 − s ) (1-s)*E=(1-s^t)/(1-s) (1−s)∗E=(1−st)/(1−s),当 t t t趋向无穷大时,有:
( 1 − s ) ∗ E = 1 / ( 1 − s ) = n / ( n − k ) (1-s)*E=1/(1-s)=n/(n-k) (1−s)∗E=1/(1−s)=n/(n−k),即答案为 ∑ k = 1 n n n − k \sum_{k=1}^{n}\frac{n}{n-k} ∑k=1nn−kn
注意输出格式
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <bitset>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
void elim(ll &x,ll &y){
ll a=x,b=y;
ll g=gcd(a,b);
x/=g,y/=g;
}
int getLen(ll x){
int ans=0;
while(x){
ans++;
x/=10;
}
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
while(~scanf("%d",&n)){
if(n==1){
printf("1\n");
continue;
}
ll u=1,d=1;
for(int i=2;i<=n;i++){
u=u*i+d;
d=d*i;
elim(u,d);
//cout<<u<<" "<<d<<endl;
}
u*=n;
elim(u,d);
if(d==1){
printf("%lld\n",u);
continue;
}
ll x=0,p=u/d,q=u%d;
x+=p,u=q;
int len1=getLen(x),len2=getLen(d);
for(int i=0;i<=len1;i++) printf(" ");
printf("%lld\n",u);
if(x) printf("%lld ",x);
for(int i=0;i<len2;i++) printf("-");
printf("\n");
for(int i=0;i<=len1;i++) printf(" ");
printf("%lld\n",d);
}
return 0;
}