Loading

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

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

题意

给定\(n,m,k\),求

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

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

分析

\[\sum \sum (i,j)^k \\ = \sum_d \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j = 1}^{\lfloor\frac{m}{d}\rfloor}[(i,j) = 1]\\ = \sum_dd^k \sum_u \mu(u) \lfloor\frac{n}{du}\rfloor\lfloor\frac{m}{du}\rfloor\\ = \sum_D\lfloor\frac{n}{D}\rfloor\lfloor\frac{m}{D}\rfloor\sum_{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\n", res);
    }
}
posted @ 2020-10-27 16:24  MQFLLY  阅读(79)  评论(0编辑  收藏  举报