BZOJ 4407 于神之怒加强版 莫比乌斯反演,线性筛

BZOJ 4407 于神之怒加强版 莫比乌斯反演,线性筛

题意

给定(n,m,k),求

[sum_{i = 1}^{n}sum_{j = 1}^{m}gcd(i,j)^k mod(1e9 + 7) ]

[1leq T leq 2000\ 1leq n,m,k leq 5e6 ]

分析

[sum sum (i,j)^k \ = sum_d sum_{i=1}^{lfloorfrac{n}{d} floor}sum_{j = 1}^{lfloorfrac{m}{d} floor}[(i,j) = 1]\ = sum_dd^k sum_u mu(u) lfloorfrac{n}{du} floorlfloorfrac{m}{du} floor\ = sum_Dlfloorfrac{n}{D} floorlfloorfrac{m}{D} floorsum_{d|D}d^{k}mu(frac{D}{d}) ]

发现后面那坨是积性函数乘积性函数,且(tmp = p ^ a)时,(f[tmp] = tmp^k - p^{(a - 1){k}}),可以在(log)时间算出

于是线性筛即可

ll f[maxn];
int prime[maxn];
int vis[maxn];
ll last[maxn];
int n, m, k;

void init() {
    f[1] = 1;
    int cnt = 0;
    for (int i = 2; i < maxn; i++) {
        if (!vis[i]) {
            prime[cnt++] = last[i] = i, f[i] = (ksm(i, k ,MOD) - 1 + MOD) % MOD;
        }
        for (int j = 0; j < cnt && i * prime[j] < maxn; j++) {
            int tmp = i * prime[j];
            vis[tmp] = 1;
            if (i % prime[j] == 0) {
                last[tmp] = last[i] * prime[j];
                if (tmp != last[tmp])
                    f[tmp] = f[i / last[i]] * f[last[tmp]] % MOD;
                else
                    f[tmp] = (ksm(tmp, k,MOD) - ksm(i, k,MOD) + MOD) % MOD;
                break;
            }
            else {
                last[tmp] = prime[j];
                f[tmp] = f[i] * f[prime[j]] % MOD;
            }
        }
    }
    for (int i = 2; i < maxn; i++)
        f[i] = f[i] + f[i - 1], f[i] %= MOD;
}

int main() {
    int T = readint();
    k = readint();
    init();
    while (T--) {
        n = readint();
        m = readint();
        ll res = 0;
        for (int l = 1,r; l <= n && l <= m; l = r + 1) {
            r = min(n / (n / l), m / (m / l));
            res += (f[r] - f[l -1] + MOD)* (n / l) % MOD* (m / l) % MOD;
            res %= MOD;
        }
        printf("%lld
", res);
    }
}
原文地址:https://www.cnblogs.com/hznumqf/p/13885555.html