喵喵题:
题意
给一个数列,每次随机选一个 (1) 到 (m) 之间的数加在数列末尾,数列中所有数的 (gcd = 1) 时停止,求期望长度, (m le 1e5)
题解
看到期望,可以用全概率公式把界限变宽,(f(x)) 表示长度 (ge x) 概率
[E(x) = sum_{i = 1} ^ infty f(i)
]
考虑如何求 (f_i) 相当于 (i) 步前面的 (gcd) 一定不为 1
考虑枚举 (gcd) 至少为 (j) 的然后把它们用容斥原理并起来
[f(x) = frac{sum_{j = 2} ^ m - mu(j) (leftlfloorfrac{m}{j}
ight
floor)^{x - 1}} {m^{x - 1}}
]
[E(x) = 1 + sum_{i = 2} ^ infty frac{sum_{j = 2} ^ m - mu(j) (leftlfloorfrac{m}{j}
ight
floor)^{i - 1}} {m^{i - 1}}
]
[= 1 - sum_{i = 1} ^ infty frac{sum_{j = 2} ^ m mu(j) (leftlfloorfrac{m}{j}
ight
floor)^{i}} {m^{i}}
]
[= 1 - sum_{j = 2} ^ m mu(j) sum_{i = 1} ^ infty (frac{leftlfloorfrac{m}{j}
ight
floor} {m})^i
]
[= 1 - sum_{j = 2} ^ m mu(j) frac{(frac{leftlfloorfrac{m}{j}
ight
floor} {m}) ^ infty - (frac{leftlfloorfrac{m}{j}
ight
floor} {m})} {(frac{leftlfloorfrac{m}{j}
ight
floor} {m}) - 1}
]
[= 1 + sum_{j = 2} ^ m mu(j) frac{(frac{leftlfloorfrac{m}{j}
ight
floor} {m})} {(frac{leftlfloorfrac{m}{j}
ight
floor} {m}) - 1}
]
[= 1 + sum_{j = 2} ^ m mu(j) frac{leftlfloorfrac{m}{j}
ight
floor} {leftlfloorfrac{m}{j}
ight
floor - m}
]
然后就做完了,写个线性求逆元就可以 (O(m)) 了
#include <bits/stdc++.h>
using namespace std;
#define gc getchar
#define rg register
#define I inline
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define per(i, a, b) for(int i = a; i >= b; --i)
I int read(){
rg char ch = gc();
rg int x = 0, f = 0;
while(!isdigit(ch)) f |= (ch == '-'), ch = gc();
while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc();
return f ? -x : x;
}
int n, m;
const int N = 1e5 + 5, mod = 1e9 + 7;
int prime[N], cnt, pre[N], mu[N];
int inv[N];
I void ola(int n){
mu[1] = 1;
rep(i, 2, n){
if(!pre[i]){
prime[++cnt] = i;
pre[i] = i;
mu[i] = -1;
}
for(int j = 1;j <= cnt && prime[j] * i <= n; ++j){
pre[i * prime[j]] = prime[j];
if(prime[j] == pre[i]){
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
}
signed main(){
m = read();
inv[1] = 1;
rep(i, 2, m) inv[i] = ((-mod / i * 1ll * inv[mod % i]) % mod + mod) % mod;
int res = 1;
ola(m);
rep(i, 2, m){
res = (res - 1ll * mu[i] * (m / i) % mod * inv[m - m / i] % mod + mod) % mod;
}
cout << res << endl;
return 0;
}