题目大意

对于给定的正整数 nnn ,定义函数 f(n)f(n)f(n) 如下:

f(n)=∑1≤p≤q≤nlcm(p,q)=n(p+q) f(n) = \sum_{\substack{1 \le p \le q \le n \\ \mathrm{lcm}(p,q) = n}} (p + q) f(n)=1pqnlcm(p,q)=n(p+q)

换句话说, f(n)f(n)f(n) 是所有满足 p≤qp \le qpqpppqqq 的最小公倍数等于 nnn 的数对 (p,q)(p, q)(p,q) 的和 (p+q)(p+q)(p+q) 的总和。

现在题目会给出 nnn 的质因数分解形式,要求计算 f(n) mod 1000000007f(n) \bmod 1000000007f(n)mod1000000007

输入格式

第一行是测试用例数 TTTT≤500T \le 500T500 )。
每个测试用例首先是一个整数 CCCC≤15C \le 15C15 ),表示 nnn 的质因子个数。
接下来 CCC 行,每行两个整数 PiP_iPiaia_iai ,表示一个质因子及其指数( PiP_iPi222100010001000 之间的素数, 1≤ai≤501 \le a_i \le 501ai50 ,所有质因子互不相同)。

输出格式

对于每个测试用例,输出一行 Case i: result ,其中 iii 是编号, resultresultresultf(n) mod 1000000007f(n) \bmod 1000000007f(n)mod1000000007 的结果。

题目分析与思路

这是一个需要推导数学公式的数论问题。直接枚举所有可能的 pppqqq 是不可行的,因为 nnn 可以很大(质因数分解形式下, nnn 本身可能远超 1010010^{100}10100 )。我们需要利用 lcm(p,q)=n\mathrm{lcm}(p,q)=nlcm(p,q)=n 的条件以及积性函数的性质。

1. 关键定义

首先定义两个辅助函数:

  • f(n)f(n)f(n) :即题目所求,只考虑 p≤qp \le qpq 的无序对。
  • F(n)F(n)F(n) :考虑所有有序对 (p,q)(p, q)(p,q) (包括 p>qp > qp>q )的和:
    F(n)=∑i=1n∑j=1n(i+j)⋅[lcm(i,j)=n] F(n) = \sum_{i=1}^{n} \sum_{j=1}^{n} (i + j) \cdot [\mathrm{lcm}(i,j)=n] F(n)=i=1nj=1n(i+j)[lcm(i,j)=n]
    其中 [P][P][P] 是指示函数,当 PPP 为真时值为 111 ,否则为 000
2. f(n)f(n)f(n)F(n)F(n)F(n) 的关系

由于 F(n)F(n)F(n) 计算了所有有序对,而 f(n)f(n)f(n) 只计算了 p≤qp \le qpq 的情况,并且当 p=q=np=q=np=q=n 时, f(n)f(n)f(n) 只计算一次 2n2n2n ,而 F(n)F(n)F(n) 也计算一次 2n2n2n 。它们的关系可以通过对称性推导:

F(n)=2f(n)−2n F(n) = 2f(n) - 2n F(n)=2f(n)2n

推导如下:在 F(n)F(n)F(n) 中,对于 p<qp<qp<q 的无序对,每个会被计算两次( (p,q)(p,q)(p,q)(q,p)(q,p)(q,p) );对于 p=qp=qp=q 的情况,只有 p=q=np=q=np=q=n 满足 lcm=n\mathrm{lcm}=nlcm=n ,这个对在 F(n)F(n)F(n) 中被算一次,在 f(n)f(n)f(n) 中也只算一次。因此 F(n)=2f(n)−2nF(n) = 2f(n) - 2nF(n)=2f(n)2n (因为 f(n)f(n)f(n)(n,n)(n,n)(n,n) 的和是 2n2n2n ,在 F(n)F(n)F(n) 中也是 2n2n2n ,但对称求和时多减了一次,调整后得到此式)。

3. 对于素数幂 pap^apaF(pa)F(p^a)F(pa)

这是推导的核心。我们需要计算当 n=pan = p^an=pa 时,所有有序对 (px,py)(p^x, p^y)(px,py) 满足 max⁡(x,y)=a\max(x,y)=amax(x,y)=a 的和 px+pyp^x + p^ypx+py

经过推导(具体过程涉及分类讨论 xxxyyy 的取值),得到公式:

  • a=1a = 1a=1 时:
    F(p)=4p+2 F(p) = 4p + 2 F(p)=4p+2

  • a≥2a \ge 2a2 时:
    F(pa)=2(a+1)pa+2(pa−p)p−1+2 F(p^a) = 2(a+1)p^a + \frac{2(p^a - p)}{p-1} + 2 F(pa)=2(a+1)pa+p12(pap)+2

4. 一般 nnnF(n)F(n)F(n)f(n)f(n)f(n)

由于 lcm(p,q)=n\mathrm{lcm}(p,q)=nlcm(p,q)=n 的条件在不同质因子上是独立的, F(n)F(n)F(n) 是一个积性函数。因此,对于 n=∏i=1kpiain = \prod_{i=1}^{k} p_i^{a_i}n=i=1kpiai ,有:

F(n)=∏i=1kF(piai)2k−1 F(n) = \frac{\prod_{i=1}^{k} F(p_i^{a_i})}{2^{k-1}} F(n)=2k1i=1kF(piai)

这里除以 2k−12^{k-1}2k1 是为了修正每个质因子独立计算时引入的重复对称因子。

然后,利用 f(n)=F(n)+2n2f(n) = \frac{F(n) + 2n}{2}f(n)=2F(n)+2n ,我们可以得到:

f(n)=n+∏i=1kF(piai)2k f(n) = n + \frac{\prod_{i=1}^{k} F(p_i^{a_i})}{2^k} f(n)=n+2ki=1kF(piai)

5. 算法步骤
  1. 读取 CCC 和每个质因子 pi,aip_i, a_ipi,ai
  2. 计算 n=∏piai mod Mn = \prod p_i^{a_i} \bmod Mn=piaimodMM=109+7M = 10^9+7M=109+7 )。
  3. 对每个质因子,根据 aia_iai 的值计算 F(piai) mod MF(p_i^{a_i}) \bmod MF(piai)modM 。注意公式中的除法需要使用模逆元。
  4. 计算所有 F(piai)F(p_i^{a_i})F(piai) 的乘积  mod M\bmod MmodM
  5. 计算 2−k mod M2^{-k} \bmod M2kmodM ,即 inv2kinv2^kinv2k ,其中 inv2=(M+1)/2inv2 = (M+1)/2inv2=(M+1)/2222 的模逆元。
  6. 最终答案:
    ans=(n+prodF×inv2k) mod M ans = \left( n + prodF \times inv2^k \right) \bmod M ans=(n+prodF×inv2k)modM

代码实现

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll MOD = 1000000007;

// 快速幂取模
ll powMod(ll a, ll e) {
    ll r = 1;
    while (e) {
        if (e & 1) r = r * a % MOD;
        a = a * a % MOD;
        e >>= 1;
    }
    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T; cin >> T;
    for (int cas = 1; cas <= T; ++cas) {
        int C; cin >> C;
        ll n = 1;                 // n 模 MOD
        ll prodF = 1;             // 所有 F(p_i^{a_i}) 的乘积
        ll inv2 = (MOD + 1) / 2;  // 2 的模逆元
        ll inv2k = 1;             // 2^{-k} 的模逆元
        while (C--) {
            ll p, a; cin >> p >> a;
            ll pa = powMod(p, a); // p^a mod MOD
            n = n * pa % MOD;     // 累积计算 n mod MOD

            ll Fi; // 计算 F(p^a) mod MOD
            if (a == 1) {
                // 公式: F(p) = 4p + 2
                Fi = (4 * pa + 2) % MOD;
            } else {
                // 公式: F(p^a) = 2(a+1)p^a + 2(p^a - p)/(p-1) + 2
                ll term1 = 2 * (a + 1) % MOD * pa % MOD;
                // 注意 (p^a - p) 可能为负,先加 MOD
                ll term2 = 2 * (pa - p + MOD) % MOD * powMod(p - 1, MOD - 2) % MOD;
                Fi = (term1 + term2 + 2) % MOD;
            }
            prodF = prodF * Fi % MOD;
            inv2k = inv2k * inv2 % MOD; // 累积 2^{-k}
        }
        ll ans = (n + prodF * inv2k % MOD) % MOD;
        cout << "Case " << cas << ": " << ans << "\n";
    }
    return 0;
}

复杂度分析

  • 时间复杂度:对于每个测试用例,需要计算 CCCF(piai)F(p_i^{a_i})F(piai) ,每个计算涉及 O(log⁡ai)O(\log a_i)O(logai) 的快速幂和常数次模运算。总复杂度为 O(Clog⁡ai)O(C \log a_i)O(Clogai) ,完全可行。
  • 空间复杂度: O(1)O(1)O(1)

总结

本题的关键在于将原问题转化为求 F(n)F(n)F(n) ,并利用积性函数的性质,将 F(n)F(n)F(n) 分解为各质因子幂的 F(pa)F(p^a)F(pa) 的乘积。推导出 F(pa)F(p^a)F(pa) 的闭合公式后,即可在模意义下高效计算。在实现时需要注意模逆元的处理以及负数取模的细节。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐