E.Sum of gcd of Tuples (Hard)

定义:

f(d)f(d)gcd(A1,A2,A3,..,An)=dgcd(A_1,A_2,A_3,..,A_n)=d的方案数

F(d)F(d)gcd(A1,A2,A3,..,An)gcd(A_1,A_2,A_3,..,A_n)dd的倍数的方案数

显然有,

F(d)=ddf(d),dd,F(d)=\sum_{d|d'}f(d'),d'为d的倍数,下面不再解释

莫比乌斯反演得

f(d)=ddμ(dd)F(d)=ddμ(dd)kdnf(d)=\sum_{d|d'} \mu(\frac{d'}{d})\cdot F(d')=\sum_{d|d'}\mu(\frac{d'}{d})\cdot\lfloor \frac{k}{d'} \rfloor^n

其中F(d)F(d')的方案数实际为满足条件[dA1,dA2,...dAn][d'|A_1,d'|A_2,...d'|A_n]'的方案数,由于AiA_i的范围为[1,k][1,k],故每个数实际上只能选择kd\lfloor \frac{k}{d'} \rfloor个,总的方案数就是kdn\lfloor \frac{k}{d'} \rfloor^n

则最终的答案可表示为

Ans=d=1kf(d)=d=1kddd(μ(dd)kdn)Ans=\sum_{d=1}^{k}f(d)=\sum_{d=1}^{k}d*\sum_{d|d'}(\mu(\frac{d'}{d})\cdot\lfloor \frac{k}{d'} \rfloor^n)

枚举[1k][1-k]倍数复杂度O(nlog(n))O(nlog(n)),照着公式写就行了。

Code

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5 + 5;
const ll mod = 1e9 + 7;
bool vis[N];
int Primes[N], mbux[N], cnt;
ll fpow[N];
ll ksm(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) {
            ans = ans * a % mod;
        }
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
void get_mbux(int n) {
    mbux[1] = 1;
    for (int i = 2; i <= n; i ++ ) {
        if(!vis[i]) {
            Primes[++ cnt] = i;
            mbux[i] = -1;
        }
        for (int j = 1; j <= cnt && i * Primes[j] <= n; j ++ ) {
            vis[i * Primes[j]] = 1;
            if(i % Primes[j] == 0) {
                mbux[i * Primes[j]] = 0; 
                break;
            }
            mbux[i * Primes[j]] = - mbux[i];
        }
    }
}

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= k; i ++ ) {
        fpow[i] = ksm(i, n);
    }
    get_mbux(k);
    ll res = 0;
    for (int i = 1; i <= k; i ++ ) {
        ll temp = 0;
        for (int j = i; j <= k; j += i) {
            temp = (temp + mbux[j/i] * fpow[k/j] % mod + mod) % mod;
        }
        res = (res + temp * i % mod + mod) % mod;
    }
    printf("%lld", res);
}