ZOJ 3881 From the ABC conjecture

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3881

题意:
问题和ABC猜想无关,定义 rad(n) 表示 n 的因子中最大的无平方因子数, φ(n) 表示不大于 n 且与 n 互质的正整数个数,令 f(n)=rad(n)φ(nrad(n)),g(n)=d|nf(d),h(n)=ni=1g(i) ,给定正整数 N ,求 h(N)mod(109+9) 的值。
n1012

题解:
n=ti=1pkii ,则 rad(n)=ti=1pi ,是一个积性函数。
而对于 (n,m)=1 ,显然有 (nrad(n),mrad(m))=1 ,则 f(nm)=rad(nm)φ(nmrad(nm))=rad(n)rad(m)φ(nrad(n))φ(mrad(m))=f(n)f(m) ,也是一个积性函数。
那么 g(n)=d|nf(d)=ti=1kij=0f(pji)=ti=1(1+pikij=1φ(pj1i))=ti=1(pkii+1)
仔细看 g(n) 的式子,相当于选出了一些 n 的约数 d 进行求和,而且每个质因数 pi 要么不选,要么选 pkii ,这样的 d 是满足 (d,nd)=1 的,因此 g(n)=d|n[(d,nd)=1]d=ni=1nj=1[(i,j)=1][ij=n]i
那么有 h(n)=nk=1ni=1nj=1[(i,j)=1][ij=k]i=ni=1nj=1[(i,j)=1][ijn]i
所以有

h(n)=i=1nj=1n[(i,j)=1][ijn]i

利用 [n=1]=d|nμ(d)
h(n)=i=1nj=1n[ijn]id[d|i][d|j]μ(d)

而当 ijn 时, dmin(i,j)n ,故有
h(n)=d=1ndμ(d)i=1nj=1n[d|i][d|j][ijn]id=d=1ndμ(d)i=1ndj=1nd[ijd2n]i

可以发现 j 很容易被消除, i 有更严格的上界,所以
h(n)=d=1ndμ(d)i=1nd2nid2i=d=1ndμ(d)s(nd2)

其中 s(n)=ni=1ini=ni=1σ(i) 可以 O(n) 计算。
注意到这里复杂度下界已经是 O(n) ,所以枚举 d 即可,不需要根据 nd2 进行分段计算。
设计算 h(n) 的时间复杂度为 T(n) ,则
T(n)=O(n+d=1nni2)=O(nd=1n1i)=O(nlogn)

代码:

#include <cmath>
#include <cstdio>
typedef long long LL;
const int maxn = 1000001, mod = 1000000009, inv2 = 500000005;
int f[maxn];
int s(LL n)
{
    int res = 0;
    for(LL i = 1, j; i <= n; i = j + 1)
    {
        j = n / (n / i);
        res = (res + n / i % mod * ((j - i + 1) % mod) % mod * ((i + j) % mod)) % mod;
    }
    res = (LL)res * inv2 % mod;
    return res;
}
int main()
{
    f[1] = 1;
    for(int i = 1; i < maxn; ++i)
    {
        for(int j = i + i; j < maxn; j += i)
            f[j] -= f[i];
        f[i] *= i;
    }
    for(LL n; scanf("%lld", &n) == 1; )
    {
        int ans = 0, lim = (int)ceil(sqrt(n));
        for(int i = 1; i <= lim; ++i)
            if(f[i])
                ans = (ans + (LL)f[i] * s(n / i / i)) % mod;
        if(ans < 0)
            ans += mod;
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(数论,线性筛,积性函数)