[HDU6868]Absolute Math

题意

f ( n ) = ∑ d ∣ n ∣ μ ( d ) ∣ \displaystyle f(n)=\sum_{d\mid n}|\mu(d)| f(n)=dnμ(d)
∑ i = 1 m f ( n i ) m o d    1 0 9 + 7 \displaystyle\sum_{i=1}^mf(ni)\mod 10^9+7 i=1mf(ni)mod109+7
1 ≤ n , m ≤ 1 0 7 1\le n,m\le10^7 1n,m107


题解

w ( n ) w(n) w(n)表示 n n n的质因子个数,根据 μ \mu μ的定义,有

f ( n ) = ∑ k = 0 w ( n ) ( w ( n ) k ) ∣ ( − 1 ) k ∣ = 2 w ( n ) \displaystyle f(n)=\sum_{k=0}^{w(n)}{w(n)\choose k}|(-1)^k|=2^{w(n)} f(n)=k=0w(n)(kw(n))(1)k=2w(n)

显然 f ( n ) f(n) f(n)是一个积性函数,且满足 f ( a b ) = f ( a ) f ( b ) f ( gcd ⁡ ( a , b ) ) \displaystyle f(ab)=\frac{f(a)f(b)}{f(\gcd(a,b))} f(ab)=f(gcd(a,b))f(a)f(b)

化简原式:
∑ i = 1 m f ( i n ) = f ( n ) ∑ i = 1 m f ( i ) f ( gcd ⁡ ( n , i ) ) = f ( n ) ∑ d ∣ n 1 f ( d ) ∑ i = 1 m f ( i ) [ gcd ⁡ ( i , n ) = d ] = f ( n ) ∑ d ∣ n 1 f ( d ) ∑ i = 1 ⌊ m d ⌋ f ( i d ) [ gcd ⁡ ( i , n d ) = 1 ] = f ( n ) ∑ d ∣ n 1 f ( d ) ∑ i = 1 ⌊ m d ⌋ f ( i d ) ∑ p ∣ i , p ∣ n d μ ( p ) = f ( n ) ∑ d ∣ n ∑ p d ∣ n μ ( p ) f ( d ) ∑ i = 1 ⌊ m p d ⌋ f ( i p d ) = f ( n ) ∑ T ∣ n ∑ d ∣ T μ ( T d ) f ( d ) ∑ i = 1 ⌊ m T ⌋ f ( i T ) = f ( n ) ∑ T ∣ n g ( T ) ∑ i = 1 ⌊ m T ⌋ f ( i T ) \begin{aligned} \sum_{i=1}^mf(in)=&f(n)\sum_{i=1}^m\frac{f(i)}{f(\gcd(n,i))}\\ &=f(n)\sum_{d\mid n}\frac1{f(d)}\sum_{i=1}^mf(i)[\gcd(i,n)=d]\\ &=f(n)\sum_{d\mid n}\frac1{f(d)}\sum_{i=1}^{\lfloor\frac md\rfloor}f(id)[\gcd(i,\frac nd)=1]\\ &=f(n)\sum_{d\mid n}\frac1{f(d)}\sum_{i=1}^{\lfloor\frac md\rfloor}f(id)\sum_{p|i,p|\frac nd}\mu(p)\\ &=f(n)\sum_{d\mid n}\sum_{pd\mid n}\frac{\mu(p)}{f(d)}\sum_{i=1}^{\lfloor\frac m{pd}\rfloor}f(ipd)\\ &=f(n)\sum_{T\mid n}\sum_{d\mid T}\frac{\mu(\frac Td)}{f(d)}\sum_{i=1}^{\lfloor\frac mT\rfloor}f(iT)\\ &=f(n)\sum_{T\mid n}g(T)\sum_{i=1}^{\lfloor\frac mT\rfloor}f(iT) \end{aligned} i=1mf(in)=f(n)i=1mf(gcd(n,i))f(i)=f(n)dnf(d)1i=1mf(i)[gcd(i,n)=d]=f(n)dnf(d)1i=1dmf(id)[gcd(i,dn)=1]=f(n)dnf(d)1i=1dmf(id)pi,pdnμ(p)=f(n)dnpdnf(d)μ(p)i=1pdmf(ipd)=f(n)TndTf(d)μ(dT)i=1Tmf(iT)=f(n)Tng(T)i=1Tmf(iT)

其中 g ( T ) = ∑ d ∣ T μ ( T d ) f ( d ) \displaystyle g(T)=\sum_{d\mid T}\frac{\mu(\frac Td)}{f(d)} g(T)=dTf(d)μ(dT),即 g = 1 f × μ \displaystyle g=\frac1f\times \mu g=f1×μ,也是一个积性函数,用线性筛的方法推导可得:

g ( T ) = { ( − 1 2 ) w ( T ) , T = ∏ i = 1 w ( T ) p i 0 , o t h e r w i s e g(T)=\left\{\begin{aligned} \Big(-\frac12\Big)^{w(T)},&&T=\prod_{i=1}^{w(T)} p_i\\ 0,&&{\rm otherwise} \end{aligned}\right. g(T)=(21)w(T),0,T=i=1w(T)piotherwise

也就是说对于 T ∣ n T\mid n Tn g ( T ) g(T) g(T),只有当 T T T n n n的质因子集合的某个子集中所有元素的乘积时,才会产生贡献。而 n ≤ 1 0 7 n\le10^7 n107时, w ( n ) ≤ 8 w(n)\le8 w(n)8,故可以在 O ( 8 ⋅ 2 8 ) O(8\cdot2^8) O(828)的时间内枚举出所有有贡献的 T T T,这样比直接枚举约数要快一些。

由于内存限制, ∑ i = 1 ⌊ m T ⌋ f ( i T ) \displaystyle \sum_{i=1}^{\lfloor\frac mT\rfloor}f(iT) i=1Tmf(iT)不能预处理。

考虑离线,把所有 ∑ i = 1 ⌊ m T ⌋ f ( i T ) \displaystyle \sum_{i=1}^{\lfloor\frac mT\rfloor}f(iT) i=1Tmf(iT)的询问,按 T T T为第一关键字, ⌊ m T ⌋ \lfloor\frac mT\rfloor Tm为第二关键字排序然后暴力计算即可。

计算答案时注意要乘上 f ( n ) g ( T ) f(n)g(T) f(n)g(T)的系数。

时间复杂度 O ( n log ⁡ n + T ( n + 8 ⋅ 2 8 ) ) O(n\log n+T(\sqrt n+8\cdot 2^8)) O(nlogn+T(n +828))

#include 
using namespace std;
const int N = 1e7 + 5, P = 1e9 + 7, Inv2 = (P + 1) / 2;
typedef long long ll;
struct Data {
    int d, m, w, id;
};
int n, m, q, Ans[10005];
int is[N], prime[N], f[N], g[N];
vector<Data> Q;
int main() {
    n = 1e7;
    f[1] = g[1] = 1;
    for (int i = 2; i <= n; ++i) {
        if (!is[i])
            prime[++prime[0]] = i, f[i] = 2, g[i] = P - Inv2;
        for (int j = 1, x; j <= prime[0] && (x = i * prime[j]) <= n; ++j) {
            is[x] = 1;
            if (i % prime[j])
                f[x] = 2 * f[i] % P, g[x] = (ll)g[prime[j]] * g[i] % P;
            else {
                f[x] = f[i];
                break;
            }
        }
    }
    scanf("%d", &q);
    for (int T = 1; T <= q; ++T) {
        scanf("%d%d", &n, &m);
        int t = n;
        vector<int> div;
        for (int d = 2; d * d <= t; ++d)
            if (t % d == 0) {
                div.push_back(d);
                while (t % d == 0)
                    t /= d;
            }
        if (t != 1)
            div.push_back(t);
        for (int s = 0; s < (1 << div.size()); ++s) {
            int d = 1;
            for (int i = 0; i <= (int)div.size() - 1; ++i)
                if (s & (1 << i))
                    d *= div[i];
            if (m < d || !g[d])
                continue;
            Q.push_back({d, (m / d) * d, int((ll)f[n] * g[d] % P), T});
        }
    }
    sort(Q.begin(), Q.end(),
         [](Data a, Data b) { return a.d == b.d ? a.m < b.m : a.d < b.d; });
    ll w;
    int d = 0, i;
    for (auto t : Q) {
        if (t.d != d)
            d = i = t.d, w = 0;
        for (; i <= t.m; i += d)
            w += f[i];
        Ans[t.id] = (Ans[t.id] + (ll)t.w * (w %= P) % P) % P;
    }
    for (int i = 1; i <= q; ++i)
        printf("%d\n", Ans[i]);
    return 0;
}

你可能感兴趣的:(#,莫比乌斯反演,数学,数论)