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) (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;
}
原文地址:https://www.cnblogs.com/XiaoVsun/p/13082591.html