【题解】CF1139D Steps to One
不太会期望题,记一下有用的想法。
思路
期望 + 莫反。
设 \(E(l)\) 为序列长度的期望,\(P(x)\) 为事件 \(x\) 发生的概率。
首先根据期望的定义有 \(E(l) = \sum\limits_{i \geq 1} P(l = i) \cdot i\)
等价于 \(E(l) = \sum\limits_{i \geq 1} P(l = i) \sum\limits_{j = 1}^i\)
即 \(E(l) = \sum\limits_{j \geq 1} \sum\limits_{i \geq j} P(l = i)\)
根据定义得 \(E(l) = \sum\limits_{i \geq 1} P(l \geq i) = 1 + \sum\limits_{i \geq 1} P(l > i)\)
考虑求出 \(P(l > i)\).
根据 \(P(l = i)\) 的定义知 \(P(l = i) = \frac{\sum\limits_{a_1 = 1}^m \cdots \sum\limits_{a_i = 1}^m [\gcd(a_1, \cdots, a_i) = 1]}{m^i}\)
所以 \(P(l > i) = \frac{\sum\limits_{a_1 = 1}^m \cdots \sum\limits_{a_i = 1}^m [\gcd(a_1, \cdots, a_i) > 1]}{m^i}\)
因为 \(\gcd(a_1, \cdots, a_i) \geq 1\),所以 \(P(\gcd(a_1, \cdots, a_i) > 1) = 1 - P(\gcd(a_1, \cdots, a_i) = 1)\)
所以 \(P(l > i) = 1 - \frac{\sum\limits_{a_1 = 1}^m \cdots \sum\limits_{a_i = 1}^m [\gcd(a_1, \cdots, a_i) = 1]}{m^i}\)
根据 \(\mu\) 的性质知 \(P(l > i) = 1 - \frac{\sum\limits_{a_1 = 1}^m \cdots \sum\limits_{a_i = 1}^m \sum\limits_{d \mid \gcd(a_1, \cdots, a_i)} \mu(d)}{m^i}\)
根据莫反套路可以推导出:\(P(l > i) = 1 - \frac{\sum\limits_{d = 1}^m \mu(d) \cdot (\lfloor \frac{m}{d} \rfloor)^i}{m^i}\)
因为 \(d = 1\) 时后一项的值等于 \(-1\),所以可以抵消:
\(P(l > i) = -\frac{\sum\limits_{d = 2}^m \mu(d) \cdot (\lfloor \frac{m}{d} \rfloor)^i}{m^i}\)
将 \(P(l > i)\) 代入回 \(E(l)\):
\(E(l) = 1 + \sum\limits_{i \geq 1} P(l > i) = 1 - \sum\limits_{i \geq 1} \frac{\sum\limits_{d = 2}^m \mu(d) \cdot (\lfloor \frac{m}{d} \rfloor)^i}{m^i}\)
整理可得 \(E(l) = 1 - \sum\limits_{d = 2}^m \sum\limits_{i \geq 1} \mu(d) \cdot (\frac{\lfloor \frac{m}{d} \rfloor}{m})^i\)
根据等比数列求和公式可以继续化简:
\(E(l) = 1 - \sum\limits_{d = 2}^m \mu(d) \cdot \frac{\lfloor \frac{m}{d} \rfloor}{m - \lfloor \frac{m}{d} \rfloor}\)
然后直接筛出 \(\mu\) 求值就行,时间复杂度 \(O(m \log V)\)
代码
#include <cstdio>
#include <vector>
#include <bitset>
using namespace std;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int n;
int mu[maxn];
vector<int> p;
bitset<maxn> vis;
int qpow(int base, int power)
{
int res = 1;
while (power)
{
if (power & 1) res = 1ll * res * base % mod;
base = 1ll * base * base % mod;
power >>= 1;
}
return res;
}
void init()
{
mu[1] = 1, vis[1] = true;
for (int i = 2; i <= n; i++)
{
if (!vis[i]) p.push_back(i), mu[i] = -1;
for (int j = 0; (j < p.size()) && (i * p[j] <= n); j++)
{
vis[i * p[j]] = true;
if (i % p[j] == 0) { mu[i * p[j]] = 0; break; }
else mu[i * p[j]] = -mu[i];
}
}
}
int main()
{
scanf("%d", &n);
init();
int ans = 1;
for (int i = 2; i <= n; i++) ans = (ans - 1ll * mu[i] * (n / i) % mod * qpow(n - n / i, mod - 2) % mod + mod) % mod;
printf("%d\n", ans);
return 0;
}