北理工乐学 NH-5 Probability
题目描述
在斗角场在你偷偷下了注,赌赢了,获得了一个小游戏资格,能免费送棒棒糖!
活动规则:在一个长度为NNN的数列的NNN个位置随机填入一个∈[1,MAX]\in [1,MAX]∈[1,MAX]的数,一个免费获得的棒棒糖数记为∑i=1N−1[gcd(ai,ai+1)=ai]\sum_{i=1}^{N - 1}[\gcd(a_i,a_{i+1})=a_i]∑i=1N−1[gcd(ai,ai+1)=ai],[gcd(ai,ai+1)=ai][\gcd(a_i,a_{i+1})=a_i][gcd(ai,ai+1)=ai]表示如果aia_iai,ai+1a_{i+1}ai+1的最大公因数等于aia_iai,则[gcd(ai,ai+1)=ai]=1[\gcd(a_i,a_{i+1})=a_i]=1[gcd(ai,ai+1)=ai]=1,否则[gcd(ai,ai+1)=ai]=0[\gcd(a_i,a_{i+1})=a_i]=0[gcd(ai,ai+1)=ai]=0。富有的你不在意你能得到几个棒棒糖,而是想计算一下你随机填数后得到免费棒棒糖的期望数量。由于你很讨厌小数,你打算将答案对109+710^9+7109+7取模。期望和取模的概念详见样例解释。
数据范围
1≤T≤6,1≤N≤1012,1≤MAX≤10121\leq T\leq 6,1\leq N\leq 10^{12},1\leq MAX\leq 10^{12}1≤T≤6,1≤N≤1012,1≤MAX≤1012,已知MAXMAXMAX不是P的倍数,(P=109+7)(P=10^9+7)(P=109+7)
题目大意
随机化一个长度为 NNN 各个值在[1,MAX][1,MAX][1,MAX]的序列,求∑i=1N−1[gcd(ai,ai+1)=ai]\sum_{i=1}^{N-1} [\gcd(a_i, a_{i+1}) = a_i]∑i=1N−1[gcd(ai,ai+1)=ai] 的期望。
分析
显然可以得到最终的答案为
∑seq∑i=1N−1[gcd(ai,ai+1)=ai]MAXN
\frac{\sum_{seq} \sum_{i=1}^{N-1}[\gcd(a_i, a_{i+1}) = a_i]}{{MAX}^N}
MAXN∑seq∑i=1N−1[gcd(ai,ai+1)=ai]
分母可以利用快速幂求出逆元,所以我们的重点就变到了如何计算分子。
显然我们不可能枚举所有的序列以计算式子,所以我们考虑计算每个 aia_iai 的贡献。
对于一个给定的 aia_iai,注意到要算它的贡献则必须把 ai+1a_{i+1}ai+1 也确定下来,而整个序列其他位置可任意取值,所以一个给定的 aia_iai 的贡献为 MAXN−2∑ai+1=1MAX[gcd(ai,ai+1)=ai]MAX^{N-2} \sum_{a_{i+1}=1}^{MAX}[\gcd(a_i,a_{i+1})=a_i]MAXN−2∑ai+1=1MAX[gcd(ai,ai+1)=ai]。而所有的 aia_iai 均等价,所以分子就可化为:
(N−1)⋅MAXN−2⋅∑ai=1MAX∑k=1MAX[gcd(ai,k)=ai] (N-1)\cdot MAX^{N-2} \cdot \sum_{a_i=1}^{MAX}\sum_{k=1}^{MAX} [\gcd(a_i, k) = a_i] (N−1)⋅MAXN−2⋅ai=1∑MAXk=1∑MAX[gcd(ai,k)=ai]
接下来计算 ∑k=1MAX[gcd(ai,k)=ai]\sum_{k=1}^{MAX}[\gcd(a_i, k)=a_i]∑k=1MAX[gcd(ai,k)=ai]:
这个式子的实际意义就是计算 aia_iai 在 [1,MAX][1,MAX][1,MAX] 上的倍数个数,显然可知这个数是 ⌊MAXai⌋\lfloor \frac{MAX}{a_i} \rfloor⌊aiMAX⌋,所以我们就仅需计算 ∑ai=1MAX⌊MAXai⌋\sum_{a_i = 1}^{MAX} \lfloor \frac{MAX}{a_i} \rfloor∑ai=1MAX⌊aiMAX⌋。
但注意到 MAXMAXMAX 值极大,我们无法直接计算这个和式,这里我选了一个比较取巧的方法(听大佬讲的)(不知道数论分块能不能做这道题,如有记得评论区评论一下)。
考虑计算 ∑i=1⌊MAX⌋⌊MAXi⌋\sum_{i=1}^{{\lfloor \sqrt{MAX} \rfloor}} \lfloor \frac{MAX}{i} \rfloor∑i=1⌊MAX⌋⌊iMAX⌋,注意到这个是可以直接计算的,不妨认为答案即为 2∑i=1⌊MAX⌋⌊MAXi⌋2\sum_{i=1}^{\lfloor \sqrt{MAX} \rfloor} \lfloor \frac{MAX}{i} \rfloor2∑i=1⌊MAX⌋⌊iMAX⌋,因为在枚举因数的时候我们仅需考虑 [1,⌊MAX⌋][1,{\lfloor \sqrt{MAX} \rfloor}][1,⌊MAX⌋] 的部分,另外一部分可简单地通过除法来取得。
但直接计算会发现答案远远超出正确值,这也意味着我们必须找出重复值。
注意到对于 iii,⌊MAXi⌋\lfloor \frac{MAX}{i} \rfloor⌊iMAX⌋ 和 ⌊iMAXi⌋\lfloor \frac{i\sqrt{MAX}}{i} \rfloor⌊iiMAX⌋ 实际上是有重复的,这是必须扣除的。简单计算得到重复的数目为 (⌊MAX⌋)2(\lfloor \sqrt{MAX} \rfloor)^2(⌊MAX⌋)2
所以,本题答案为
(N−1)⋅MAXN−2⋅(2×∑i=1⌊MAX⌋−(⌊MAX⌋)2)MAXN \frac{(N-1) \cdot MAX^{N-2} \cdot (2\times \sum_{i=1}^{\lfloor \sqrt{MAX} \rfloor} - (\lfloor \sqrt{MAX} \rfloor)^2)}{MAX^N} MAXN(N−1)⋅MAXN−2⋅(2×∑i=1⌊MAX⌋−(⌊MAX⌋)2)
注意到本题数据极大,进行快速幂前应先对底数取模以保证数据不会炸 long long(我因为这个问题调了好久)。
参考代码
#include <stdio.h>
#include <math.h>
const long long Mod = (long long)1E9 + 7;
long long quickpow(long long a, long long n) {
a %= Mod;
long long ret = 1;
while(n) {
if(n & 1) ret = (ret * a) % Mod;
a = (a * a) % Mod, n >>= 1;
}
return ret;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
long long N, M;
scanf("%lld %lld", &N, &M);
if(N == 1) {puts("0"); continue;}
long long sum = 0;
for(long long i = 1; i * i <= M; i++)
sum = (sum + (M / i)) % Mod;
sum = (sum * 2 % Mod - ((long long)(sqrt(M)) * (long long)(sqrt(M)) % Mod) + Mod) % Mod;
sum = ((sum * ((N - 1) % Mod)) % Mod) * quickpow(M, N - 2) % Mod;
printf("%lld\n", sum * quickpow(quickpow(M, N), Mod - 2) % Mod);
}
return 0;
}

文章讨论了一种数学问题,即在长度为N的数列中随机填充[1,MAX]之间的数,然后计算满足特定条件(相邻两项的最大公因数等于当前项)的棒棒糖数量的期望。通过对序列中每个数的贡献进行分析,提出了一种利用快速幂计算期望的策略,该策略涉及计算每个数在MAX的所有倍数中的出现次数,并处理重复项。最后,给出了一个C++代码片段来实现这个算法。

被折叠的 条评论
为什么被折叠?



