CF1139D Steps to One

喵喵题:

题意

给一个数列,每次随机选一个 \(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) (\left\lfloor\frac{m}{j}\right\rfloor)^{x - 1}} {m^{x - 1}} \]

\[E(x) = 1 + \sum_{i = 2} ^ \infty \frac{\sum_{j = 2} ^ m - \mu(j) (\left\lfloor\frac{m}{j}\right\rfloor)^{i - 1}} {m^{i - 1}} \]

\[= 1 - \sum_{i = 1} ^ \infty \frac{\sum_{j = 2} ^ m \mu(j) (\left\lfloor\frac{m}{j}\right\rfloor)^{i}} {m^{i}} \]

\[= 1 - \sum_{j = 2} ^ m \mu(j) \sum_{i = 1} ^ \infty (\frac{\left\lfloor\frac{m}{j}\right\rfloor} {m})^i \]

\[= 1 - \sum_{j = 2} ^ m \mu(j) \frac{(\frac{\left\lfloor\frac{m}{j}\right\rfloor} {m}) ^ \infty - (\frac{\left\lfloor\frac{m}{j}\right\rfloor} {m})} {(\frac{\left\lfloor\frac{m}{j}\right\rfloor} {m}) - 1} \]

\[= 1 + \sum_{j = 2} ^ m \mu(j) \frac{(\frac{\left\lfloor\frac{m}{j}\right\rfloor} {m})} {(\frac{\left\lfloor\frac{m}{j}\right\rfloor} {m}) - 1} \]

\[= 1 + \sum_{j = 2} ^ m \mu(j) \frac{\left\lfloor\frac{m}{j}\right\rfloor} {\left\lfloor\frac{m}{j}\right\rfloor - 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;
}
posted @ 2020-06-10 07:44  __int256  阅读(135)  评论(1编辑  收藏  举报