【Coel.个人题解】【首次出题w】高考数学

题前闲话

很高兴能够给模拟赛出一道题目,感谢 Sherlockk 的支持w
虽然这道题甚至都还没有用上(本题解撰写于 6 月 19 日),不过我提前码上来应该没人发现吧(小声
直接隐藏不就好了吗

题目描述

给出两个正整数 \(n,m\),随机从 \(n\)\(m\) 的整数中选取 \(2\) 个不同的整数,求出这 \(2\) 个数互质的概率,并用分数形式表示。

两个数互质定义为两个数除了 \(1\) 以外,没有其它的公约数。

解题思路

三步走:算分子,算分母,然后约分。
\(n\)\(m\) 可选数字个数为 \(k\) ,可以知道 \(k=m-n+1\),那么分母就是 \(C^2_k\)
接下来推推式子:

\[C^2_k=\dfrac{k!}{2!(k-2)!}=\dfrac{k(k-1)(k-2)...\times2\times1}{2(k-2)(k-3)...\times2\times1}=\dfrac{k(k-1)}{2} \]

这样就能以 \(O(1)\) 的复杂度求出分母。
约分相信大家小学时就已经学过,是把分子分母同时除以它们的最大公约数。algorithm 头文件里提供了一个函数 __gcd(n,m) 可以求最大公约数,如果不会辗转相除法可以用这个。
接下来是重点:怎么求分子?
这就要用到莫比乌斯反演了。
考察我们要求的分子,其实可以表示为:

\[\sum_{i=n}^m\sum_{j=i+1}^m[\gcd(i,j)=1] \]

中括号表示内部结果正确则结果为 \(1\) ,反之为 \(0\)
上式其实就代表了暴力求解的过程。
这个式子不太好化(因为 \(j\) 的起始值不定),但不妨换个方向,原式可以改写成:

\[\frac{\sum_{i=n}^m\sum_{j=n}^m[\gcd(i,j)=1]}{2} \]

上式是说,让 \(i,j\) 都从 \(n\) 开始枚举。这样做会重复算,除以二就好了。
再根据容斥原理,我们可以把式子分成四份处理,这一点类似于二维前缀和的计算方法。这里只给出结论:四份对应的式子为

\[S_1=\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m[\gcd(i,j)=1] \]

\[S_2=\frac{1}{2}\sum_{i=1}^{n-1}\sum_{j=1}^{m}[\gcd(i,j)=1] \]

\[S_3=\frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{n-1}[\gcd(i,j)=1] \]

\[S_4=\frac{1}{2}\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(i,j)=1] \]

结果为 \(S_1-S_2-S_3+S_4\)
显然,这四个式子都可以看做如下形式:

\[\frac{1}{2}\sum_{i=1}^a\sum_{j=1}^b[\gcd(i,j)=1] \]

那么我们就以这个形式为例进行推导。
由于 \(\gcd=1\) 的时候才会对原式产生贡献,这与狄利克雷卷积单位元的定义(\(\varepsilon(n)=1\) 当且仅当 \(n=1\),否则 \(\varepsilon(n)=0\))是一致的。所以将其代入:

\[\frac{1}{2}\sum_{i=1}^a\sum_{j=1}^b\varepsilon(\gcd(i,j)) \]

利用单位元的性质将其展开:

\[\frac{1}{2}\sum_{i=1}^a\sum_{j=1}^b\sum_{d\mid \gcd(i,j)}\mu(d) \]

\(d\mid\gcd(i,j)\) 表示枚举所有能够整除 \(\gcd(i,j)\) 的值 \(d\)
顺带一提,

\[[\gcd(i,j)=1]=\sum_{d\mid \gcd(i,j)}\mu(d) \]

就是莫比乌斯反演的结论。这个结论也可以不使用单位元而证明出,此处不再详述,感兴趣的同学可以试着推导一下。
改变一下求和顺序,把枚举符合条件的 \(d\) 放在式子前面进行:

\[\frac{1}{2}\sum_{d=1}\mu(d)\sum_{i=1}^{a}[d\mid i]\sum_{j=1}^{b}[d\mid j] \]

最后,由于 \([1,m]\)\(d\) 的倍数有 \(\lfloor \dfrac{m}{d} \rfloor\) 个(\(\lfloor\rfloor\) 表示向下取整),进一步化简:

\[\frac{1}{2}\sum_{d=1}^{\min(a,b)}\mu(d)\lfloor\frac a d\rfloor\lfloor\frac b d\rfloor \]

呼……式子终于化完了!
那么怎么计算呢?
首先 \(\mu(d)\) 是一个积性函数,可以用类似筛质数的方法全部预处理出来,这个过程的时间复杂度是 \(O(n)\) 的。
接下来,对于上面的式子如果直接暴力代入求和,处理单个数据的时间复杂度为 \(O(m)\) (这里忽略掉了求最大公约数的时间复杂度),理论上无法通过(然而还是被 Sherlockk 卡过了……)
可以使用一种特殊的数据结构:数论分块。它的原理是把相同的 \(\lfloor \dfrac{n}{d} \rfloor\) 合在一起计算,把时间复杂度压缩到 \(O(\sqrt m)\)
为了节省篇幅,这里只给出预处理 \(\mu(d)\) 的代码以及代式子的代码供参考:

void init() { //预处理莫比乌斯函数
    int tot = 0;
    mu[1] = 1;
    for (int i = 2; i <= maxn - 10; i++) {
        if (!vis[i]) {
            p[++tot] = i;
            mu[i] = -1;
        }
        for (int j = 1; j <= tot && i * p[j] <= maxn - 10; j++) {
              vis[i * p[j]] = 1;
              if (i % p[j] == 0) {
                  mu[i * p[j]] = 0;
                  break;
              }
              mu[i * p[j]] = -mu[i];
        }
    }
    for (int i = 1; i <= maxn - 10; i++)
        mu[i] += mu[i - 1];
}

int solve(int n, int m) { //推出的式子
    int res = 0;
    for (int i = 1, j; i <= min(n, m); i = j + 1) {
        j = min(n / (n / i), m / (m / i));
        res += (mu[j] - mu[i - 1]) * (n / i) * (m / i);
    }
    return res;
}

结语

第一次出题感觉有点毒瘤,如果影响到了大家的比赛体验,那只能说句抱歉了qwq
后记:实际上区间中位数比这个毒瘤一点。

posted @ 2022-06-19 15:37  秋泉こあい  阅读(53)  评论(0编辑  收藏  举报