HDU6715 算术 [莫比乌斯函数]

算术

题目描述见链接 .


color{red}{正解部分}

现在要求解 i=1nj=1mμ(lcm(i,j))sumlimits_{i=1}^nsumlimits_{j=1}^mmu(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))=0mu(lcm(i, j)) = 0, 说明 ijgcd(i,j)frac{ij}{gcd(i, j)} 分解质因数后含有幂数超过 11 的质因子, 设其为 pp,
pip | ip∤ jp ot| j, 则 μ(i)=0mu(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)=0mu(i) = 0, 此时上式成立 .

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

, herefore 综上所述, 上式成立

所以原式 i=1nj=1mμ(i)μ(j)μ(gcd(i,j))sumlimits_{i=1}^nsumlimits_{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]sumlimits_{d=1}^{min(n,m)}mu(d)sumlimits_{i=1}^{lfloorfrac{n}{d} floor}sumlimits_{j=1}^{lfloorfrac{m}{d} floor}mu(id)mu(jd)[gcd(i,j)==1]

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

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

T=dkT = dk,

T=1min(n,m)dTμ(d)μ(Td)i=1nTμ(iT)j=1mTμ(jT)sumlimits_{T=1}^{min(n,m)}sumlimits_{dmid T}mu(d)mu(frac{T}{d})sumlimits_{i=1}^{lfloorfrac{n}{T} floor}mu(iT)sumlimits_{j=1}^{lfloorfrac{m}{T} floor}mu(jT)

color{red}{实现部分}

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

T=1min(n,m)(dTμ(d)μ(Td))(i=1nTμ(iT))(j=1mTμ(jT))sumlimits_{T=1}^{min(n,m)} left(sumlimits_{dmid T}mu(d)mu(frac{T}{d}) ight) left(sumlimits_{i=1}^{lfloorfrac{n}{T} floor}mu(iT) ight) left(sumlimits_{j=1}^{lfloorfrac{m}{T} floor}mu(jT) ight)
#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
", Ans);
}

int main(){
        Init();
        int test_cnt = read();
        while(test_cnt --) Work();
        return 0;
}
原文地址:https://www.cnblogs.com/zbr162/p/11822443.html