[2021 CCCC天梯赛] 可怜的简单题 (概率期望 莫比乌斯反演 杜教筛)

题意

每次从 [ 1 , n ] [1,n] [1,n] 中选择一个数加到一个序列末尾,当 gcd ⁡ ( a 1 , ⋯   , a n ) = 1 \gcd(a_1,\cdots,a_n)=1 gcd(a1,,an)=1 时停止,求期望长度,对 p p p 取模

1 ≤ n ≤ 1 0 11 , n < p ≤ 1 0 12 1\le n \le 10^{11},n< p \le 10 ^{12} 1n1011,n<p1012

分析:

E ( x ) E(x) E(x) 为长度为 x x x 的期望,那么根据期望定义

E ( x ) = ∑ i = 1 ∞ P ( x = i ) × i E(x)=\sum_{i=1}^{\infty}P(x=i) \times i E(x)=i=1P(x=i)×i

i i i 改为 ∑ j = 1 i \sum\limits_{j=1} ^{i} j=1i

E ( x ) = ∑ i = 1 ∞ P ( x = i ) ∑ j = 1 i E(x)=\sum_{i=1}^{\infty}P(x=i) \sum_{j=1}^{i} E(x)=i=1P(x=i)j=1i

交换求和次序

∑ i = 1 ∞ ∑ j = i ∞ P ( x = j ) \sum_{i=1}^{\infty}\sum_{j = i}^{\infty}P(x=j) i=1j=iP(x=j)

等价于

∑ i = 1 ∞ P ( x ≥ i ) \sum_{i=1}^{\infty}P(x\ge i) i=1P(xi)

化简一下

∑ i = 1 ∞ P ( x ≥ i ) = 1 + ∑ i = 1 ∞ P ( x > i ) \sum_{i=1}^{\infty}P(x\ge i)=1+\sum_{i=1}^{\infty}P(x> i) i=1P(xi)=1+i=1P(x>i)

考虑 P ( x > i ) P(x> i) P(x>i),进行容斥 1 − P ( x ≤ i ) 1-P(x \le i) 1P(xi) 就等价于

1 − P ( gcd ⁡ ( a 1 , ⋯   , a i ) = 1 ) 1-P(\gcd(a_1,\cdots,a_i)=1) 1P(gcd(a1,,ai)=1)

枚举 a i a_i ai [ 1 , n ] [1,n] [1,n] 中的取值

1 − ∑ a 1 = 1 n ⋯ ∑ a i = 1 n [ gcd ⁡ ( a 1 , ⋯   , a i ) = 1 ] n i 1-\sum_{a_1=1}^{n}\cdots\sum_{a_i=1}^{n}\frac{[\gcd(a_1,\cdots,a_i)=1]}{n^{i}} 1a1=1nai=1nni[gcd(a1,,ai)=1]

莫比乌斯反演

1 − ∑ a 1 = 1 n ⋯ ∑ a i = 1 n ∑ d ∣ gcd ⁡ ( a 1 , ⋯   , a i ) μ ( d ) n i 1-\sum_{a_1=1}^{n}\cdots\sum_{a_i=1}^{n}\frac{\sum\limits_{d \mid\gcd(a_1,\cdots,a_i) }\mu(d)}{n^{i}} 1a1=1nai=1nnidgcd(a1,,ai)μ(d)

交换求和次序

1 − ∑ d = 1 n μ ( d ) ⌊ n d ⌋ i n i 1-\frac{\sum\limits_{d=1}^{n}\mu(d)\lfloor \dfrac{n}{d} \rfloor^i}{n^i} 1nid=1nμ(d)dni

1 1 1 拿到分子,和第一项抵消了

− ∑ d = 2 n μ ( d ) ⌊ n d ⌋ i n i -\frac{\sum\limits_{d=2}^{n}\mu(d)\lfloor \dfrac{n}{d} \rfloor^i}{n^{i}} nid=2nμ(d)dni

代入到 1 + ∑ i = 1 ∞ P ( l e n > i ) 1+\sum\limits_{i=1}^{\infty}P(len > i) 1+i=1P(len>i)

1 − ∑ i = 1 ∞ ∑ d = 2 n μ ( d ) ⌊ n d ⌋ i n i 1-\sum_{i=1}^{\infty}\frac{\sum\limits_{d=2}^{n}\mu(d)\lfloor \dfrac{n}{d} \rfloor^i}{n^{i}} 1i=1nid=2nμ(d)dni

交换求和次序

1 − ∑ d = 2 n μ ( d ) ∑ i = 1 ∞ ( ⌊ n d ⌋ n ) i 1-\sum_{d=2}^{n}\mu(d)\sum_{i=1}^{\infty}(\frac{\lfloor \dfrac{n}{d} \rfloor}{n})^i 1d=2nμ(d)i=1(ndn)i

∑ i = 1 ∞ ( ⌊ n d ⌋ n ) i \sum\limits_{i=1}^{\infty}(\dfrac{\lfloor \dfrac{n}{d} \rfloor}{n})^i i=1(ndn)i 这是个等比级数,极限为 首 项 1 − 公 比 \dfrac{首项}{1-公比} 1

1 − ∑ d = 2 n μ ( d ) ⌊ n d ⌋ n − ⌊ n d ⌋ 1-\sum_{d=2}^{n}\mu(d)\frac{\lfloor \dfrac{n}{d} \rfloor}{n-\lfloor \dfrac{n}{d} \rfloor} 1d=2nμ(d)ndndn

就可以用杜教筛了

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
    cin.tie(0) -> sync_with_stdio(0);
    int n, mod;
    cin >> n >> mod;
    int cnt = 0, N = 2.2e7 + 5;
    vector<int> primes(N), mobius(N), sum(N);
    vector<bool> st(N);
    auto sieve = [&](int n) {
        mobius[1] = 1;
        for (int i = 2; i <= n; i ++) {
            if (!st[i]) {
                primes[cnt ++] = i;
                mobius[i] = -1;
            }
            for (int j = 0; i * primes[j] <= n; j ++) {
                int t = i * primes[j];
                st[t] = 1;
                if (i % primes[j] == 0) {
                    mobius[t] = 0;
                    break;
                }
                mobius[t] = -mobius[i];
            }
        }
        for (int i = 1; i <= n; i ++) {
        	sum[i] = (sum[i - 1] + mobius[i] + mod) % mod;
        }
    };
    sieve(N - 1);
    auto qmul = [&](int a, int b) {
    	return (__int128)a * b % mod;
    };
    auto qmi = [&](int a, int b) {
    	int res = 1;
    	while (b) {
    		if (b & 1) res = qmul(res, a);
    		a = qmul(a, a);
    		b >>= 1;
    	}
    	return res;
    };
    unordered_map<int, int> mp;
    function<int(int)> Sum = [&](int n) {
    	if (n < N) return sum[n];
    	if (mp[n]) return mp[n];
    	int res = 1;
    	for (int l = 2, r; l <= n; l = r + 1) {
    		r = n / (n / l);
    		res = (res - qmul(r - l + 1, Sum(n / l)) % mod + mod) % mod;
    	}
    	return mp[n] = res;
    };
    int res = 1;
    for (int l = 2, r; l <= n; l = r + 1) {
    	r = n / (n / l);
    	int t = qmul(n / l, qmi(n - n / l, mod - 2));
    	res = (res - qmul(Sum(r) - Sum(l - 1), t) + mod) % mod;
    }
    cout << res << endl;
}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值