[数论]HDU 6750 Function 百度之星2020初赛第一场H题

HDU 6750 Function

百度之星2020初赛第一场H题

题目大意

\(f(n)=\sum_{d|n}d[gcd(d,\frac{n}{d})=1]\),
\(S(n)=\sum_{i=1}^{n}f(i)\)
\(1\leq n\leq 10^{12}\)

题解

不难发现 \(f(n)\) 是积性函数,证明如下:
\(gcd(n,m)=1\),
\(f(n)=\sum_{d|n}d[gcd(d,\frac{n}{d})=1]\),
\(f(m)=\sum_{d|m}d[gcd(d,\frac{m}{d})=1]\),
\(f(nm)=\sum_{d|nm}d[gcd(d,\frac{nm}{d})=1]\),
\(f(n)f(m)=\left(\sum_{d|n}d[gcd(d,\frac{n}{d})=1]\right)\left(\sum_{d|m}d[gcd(d,\frac{m}{d})=1]\right)\)
\(=\sum_{d|n}\sum_{p|m}dp[gcd(d,\frac{n}{d})=1][gcd(p,\frac{m}{p})=1]\)
\(=\sum_{d|n}\sum_{p|m}dp[gcd(dp,\frac{nm}{dp})=1]\)
\(=\sum_{dp|nm}dp[gcd(dp,\frac{nm}{dp})=1]\)
\(=\sum_{d|nm}d[gcd(d,\frac{nm}{d})=1]\)
\(=f(nm)\)
所以 \(f(n)\) 是积性函数,我们要求的 \(S(n)\) 是一个积性函数的前缀和。

考虑构造两个积性函数 \(g\)\(h\),使得 \(f=g*h\),
\(f(n)=\sum_{d|n}g(\frac{n}{d})h(d)\)
那么 \(S(n)=\sum_{i=1}^{n}f(i)=\sum_{i=1}^{n}\sum_{d|i}g(\frac{i}{d})h(d)=\sum_{d=1}^{n}\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}g(i)h(d)\)

因为 \(n\) 的范围非常大,式子中的 \(h(d)\) 不太好处理。我们期望降低 \(d\) 的枚举范围。

考虑当 \(n=p,p\in Prime\) 的情况,
\(f(p)=\sum_{d|p}g(d)h(\frac{p}{d})=g(1)h(p)+g(p)h(1)=h(p)+g(p)\),
又由 \(f(n)=\sum_{d|n}d[gcd(d,\frac{n}{d})=1]\) 得, \(f(p)=1+p\)
我们希望\(\forall p\in Prime,h(p)=0\), 此时\(f(p)=g(p)=1+p\)
发现 \(\sigma_1(n)=\sum_{d|n}d, \sigma_1(p)=1+p\),所以我们不妨令 \(g(n)=\sigma_1(n)\)
现在的问题是 \(h(n)\) 是什么。

再考虑当 \(n=p^2,p\in Prime\) 的情况,
\(f(p^2)=\sum_{d|p^2}\sigma_1(d)h(\frac{p^2}{d})=\sigma_1(1)h(p^2)+\sigma_1(p)h(p)+\sigma_1(p^2)h(1)\)
\(=h(p^2)+\sigma_1(p^2)=h(p^2)+1+p+p^2\)
又由于 \(f(p^2)=1+p^2\), 所以 \(h(p^2)=-p\)

再考虑当 \(n=p^e,p\in Prime,e>2\) 的情况。
\(f(p^e)=\sum_{d|p^e}\sigma_1(d)h(\frac{p^e}{d})=\sigma_1(p^0)h(p^e)+\sigma_1(p)h(p^{e-1})+\dots+\sigma_1(p^{e-2})h(p^2)+\sigma_1(p^{e-1})h(p^1)+\sigma_1(p^e)h(p^0)\)
\(=\sigma_1(p^0)h(p^e)+\sigma_1(p)h(p^{e-1})+\dots+\sigma_1(p^{e-3})h(p^3)-p\sigma_1(p^{e-2})+\sigma_1(p^e)\)
\(=\sigma_1(p^0)h(p^e)+\sigma_1(p)h(p^{e-1})+\dots+\sigma_1(p^{e-3})h(p^3)-p(1+p+\dots+p^{e-2})+(1+p+\dots+p^e)\)
\(=\sigma_1(p^0)h(p^e)+\sigma_1(p)h(p^{e-1})+\dots+\sigma_1(p^{e-3})h(p^3)+1+p^e\)
又因为 \(f(p^e)=1+p^e\)
所以当 \(p\in Prime,e>2\) 时,\(h(p^e)=0\)

综上 \(h(1)=1,h(p)=0,h(p^2)=-p,h(p^e)=0,e>2\)
不妨令 \(t(n)=h(n^2)\)
发现 \(h(n)\) 对素数的平方比较特殊,考虑到到莫比乌斯函数 \(\mu(n)\) 的性质,得 \(h(p^2)=\mu(p)p=-p\)
考虑到 \(h(n)\) 也是积性函数,
\(h(n)=h(p_1^{k_1}p_2^{k_2}\dots p_m^{k_m})=h(p_1^{k_1})h(p_2^{k_2})\dots h(p_m^{k_m})\)
根据前面的性质,只有当n的所有质因子的质数 \(k_i\) 均为2时,\(h(n)\) 才不为0。所以对于不为0的 \(h(n)\),\(n\)的最大质因子一定小于等于 \(\sqrt n\)
所以 \(S(n)=\sum_{d=1}^{n}\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sigma_1(i)h(d)=\sum_{d=1}^{\sqrt n} h(d^2)\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sigma_1(i)=\sum_{d=1}^{\sqrt n} \mu(d)d\sum_{i=1}^{\left\lfloor\frac{n}{d^2}\right\rfloor}\sigma_1(i)\)
显然对于后面的 \(\sum_{i=1}^{\left\lfloor\frac{n}{d^2}\right\rfloor}\sigma_1(i)\) 我们又可以整除分块来做。
约数个数和函数 \(\sigma_1(n)\) 的前缀和同样也可以由 \(\sum_{i=1}^{n}\sigma_1(n)=\sum_{i=1}^{n}\sum_{d|i}d=\sum_{d=1}^{n}d\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}1=\sum_{d=1}^{n}d\left\lfloor\frac{n}{d}\right\rfloor\) 使用整除分块求出。
官方题解指出时间复杂度为 \(O(\sqrt n \log n)\),但我并不会证。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;

#define RG register int
#define LL long long
const LL MOD=1000000007LL;
const LL Inv2=500000004LL;

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

const int maxn=1000000;
vector<int> Prime;
int Mu[maxn+5];
LL Sum[maxn+5];
bool not_Prime[maxn+5];

void Get_Mu(int Len){
    not_Prime[1]=1;
    Mu[1]=1;
    for(RG i=2;i<=Len;i++) {
        if(!not_Prime[i]){
            Prime.push_back(i);Mu[i]=-1;
        }
        for(RG j=0;j<(int)Prime.size();++j) {
            LL mid=(LL)Prime[j]*i;
            if(mid>Len) break;
            not_Prime[mid]=1;
            if(i%Prime[j]==0) {Mu[mid]=0;break;}
            Mu[mid]=-Mu[i];
        }
    }
    for(RG i=1;i<=maxn;++i)
        Sum[i]=((Sum[i-1]+(LL)Mu[i]*i%MOD)%MOD+MOD)%MOD;
    return;
}

LL Sigma1(LL n){
    LL Res=0;
    for(LL L=1,R;L<=n;L=R+1){
        R=n/(n/L);
        LL temp=(L+R)%MOD*((R-L+1)%MOD)%MOD*Inv2%MOD;
        Res=((Res+temp*(n/L)%MOD)%MOD+MOD)%MOD;
    }
    return Res;
}

LL Calc(LL n){
    LL Res=0;
    LL m=sqrt(n);
    for(LL L=1,R;L<=m;L=R+1){
        R=min((LL)sqrt(n/(n/L/L)),m);
        Res=((Res+(Sum[R]-Sum[L-1])%MOD*Sigma1(n/L/L)%MOD)%MOD+MOD)%MOD;
    }
    return Res;
}

int main(){
    Get_Mu(maxn);
    int T;LL n;
    Read(T);
    while(T--){
        Read(n);
        printf("%lld\n",Calc(n));
    }
    return 0;
}
posted @ 2020-07-20 15:19  AE酱  阅读(348)  评论(0编辑  收藏  举报