HDU6715 算术 [莫比乌斯函数]

算术

题目描述见链接 .


\color{red}{正解部分}

现在要求解 i=1nj=1mμ(lcm(i,j))\sum\limits_{i=1}^n\sum\limits_{j=1}^m\mu(lcm(i,j)),

因为 μ(lcm(i,j))=μ(i)μ(j)μ(gcd(i,j))\mu(lcm(i,j)) = \mu(i)\mu(j)\mu(gcd(i,j)),

:

假设 μ(lcm(i,j))=0\mu(lcm(i, j)) = 0, 说明 ijgcd(i,j)\frac{ij}{gcd(i, j)} 分解质因数后含有幂数超过 11 的质因子, 设其为 pp,
pip | ip∤ jp \not| \ j, 则 μ(i)=0\mu(i)=0, 此时上式成立 .
pip | ipjp | j, 设在 iipp 的幂数为 aa, jj 中的幂数为 bb, 则 a+bmin(a,b)>1a+b - \min(a, b) > 1, 令 a>ba > b, 则 a>1a > 1, 此时 μ(i)=0\mu(i) = 0, 此时上式成立 .

假设 μ(lcm(i,j))0\mu(lcm(i, j)) \not= 0, 则幂数相加的奇偶性与幂数相减的奇偶性相同, 不会改变 μ\mu 取值, 上式成立 .

,\therefore 综上所述, 上式成立

所以原式 i=1nj=1mμ(i)μ(j)μ(gcd(i,j))\sum\limits_{i=1}^n\sum\limits_{j=1}^m \mu(i)\mu(j)\mu(gcd(i,j)),
枚举 d=gcd(i,j)d = gcd(i, j)

d=1min(n,m)μ(d)i=1ndj=1mdμ(id)μ(jd)[gcd(i,j)==1]\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}\mu(id)\mu(jd)[gcd(i,j)==1]

根据 这里 所述的 μ\mu 性质 22,

d=1min(n,m)μ(d)i=1ndj=1mdμ(id)μ(jd)kgcd(i,j)μ(k)\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}\mu(id)\mu(jd)\sum\limits_{k|gcd(i,j)} \mu(k)
d=1min(n,m)μ(d)k=1min(n,m)dμ(k)i=1nkdj=1mkdμ(idk)μ(jdk)\sum\limits_{d=1}^{\min(n, m)}\mu(d) \sum\limits_{k=1}^{\lfloor \frac{\min(n, m)}{d} \rfloor } \mu(k) \sum\limits_{i=1}^{\lfloor \frac{n}{kd} \rfloor} \sum\limits_{j=1}^{\lfloor \frac{m}{kd} \rfloor} \mu(idk)\mu(jdk)

T=dkT = dk,

T=1min(n,m)dTμ(d)μ(Td)i=1nTμ(iT)j=1mTμ(jT)\sum\limits_{T=1}^{\min(n,m)}\sum\limits_{d\mid T}\mu(d)\mu(\frac{T}{d})\sum\limits_{i=1}^{\lfloor\frac{n}{T}\rfloor}\mu(iT)\sum\limits_{j=1}^{\lfloor\frac{m}{T}\rfloor}\mu(jT)

\color{red}{实现部分}

预处理括号内元素即可实现 O(NlogN)O(N\log N) 计算答案 .

T=1min(n,m)(dTμ(d)μ(Td))(i=1nTμ(iT))(j=1mTμ(jT))\sum\limits_{T=1}^{\min(n,m)} \left(\sum\limits_{d\mid T}\mu(d)\mu(\frac{T}{d}) \right) \left(\sum\limits_{i=1}^{\lfloor\frac{n}{T}\rfloor}\mu(iT) \right) \left(\sum\limits_{j=1}^{\lfloor\frac{m}{T}\rfloor}\mu(jT)\right)
#include<bits/stdc++.h>
#define reg register
typedef long long ll;

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 1e6 + 5;
const int lim  = 1e6;

int N;
int M;
int pc;
int p[maxn];
int mu[maxn];
int s2[maxn];
int s3[maxn];
int vis[maxn];
int s1[maxn+1];

void Init(){
        mu[1] = 1; 
        for(reg int i = 2; i <= lim; i ++){
                if(!vis[i]) p[++ pc] = i, mu[i] = -1;
                for(reg int j = 1; j <= pc && p[j]*i <= lim; j ++){
                        vis[p[j]*i] = 1;
                        if(i % p[j] == 0){ mu[p[j]*i] = 0; break ; }
                        mu[p[j]*i] = -mu[i];
                }
        }
        for(reg int i = 1; i <= lim; i ++)
                for(reg int j = 1; j <= lim/i; j ++) s1[i*j] += mu[i] * mu[j];
}

void Work(){
        memset(s2, 0, sizeof s2); memset(s3, 0, sizeof s3);
        N = read(), M = read();
        for(reg int i = 1; i <= N; i ++)
                for(reg int j = 1; j <= N/i; j ++) s2[i] += mu[i * j];
        for(reg int i = 1; i <= M; i ++)
                for(reg int j = 1; j <= M/i; j ++) s3[i] += mu[i * j];
        N = std::min(N, M);
        ll Ans = 0;
        for(reg int i = 1; i <= N; i ++) Ans += 1ll*s1[i]*s2[i]*s3[i];
        printf("%lld\n", Ans);
}

int main(){
        Init();
        int test_cnt = read();
        while(test_cnt --) Work();
        return 0;
}
posted @ 2019-08-25 21:12  XXX_Zbr  阅读(140)  评论(0编辑  收藏  举报