[计蒜客] tsy's number 解题报告 (莫比乌斯反演+数论分块)

interlinkage:

https://nanti.jisuanke.com/t/38226

description:

solution:

显然$\frac{\phi(j^2)}{\phi(j)}=j,\frac{\phi(k^3)}{\phi(k)}=k^2$

原式可以化简为

$\sum_{i=1}^{n}\sum_{j=1}^n\sum_{k=1}^{n}jk^2\phi(gcd(i,j,k))$

我们枚举$gcd(i,j,k)$,得

$\sum_{d=1}^{n}\phi(d)\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^njk^2[gcd(i,j,k)==d]$

$\sum_{d=1}^{n}\phi(d)\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{k=1}^{n/d}jk^2d^3[gcd(i,j,k)==1]$

$\sum_{d=1}^{n}\phi(d)\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{k=1}^{n/d}jk^2d^3\sum_{s|gcd(i,j,k)}\mu(s)$

设$sum1(n)=\sum_{i=1}^{n}i,sum2(n)=\sum_{i=1}^{n}i^2$

$\sum_{d=1}^{n}\phi(d)\sum_{i=1}^{n/d}\mu(i) \lfloor\frac{n}{id}\rfloor sum1(\lfloor\frac{n}{id}\rfloor) sum2(\lfloor\frac{n}{id}\rfloor)i^3d^3$

枚举$id$

$\sum_{T=1}^{n}\phi*\mu(T) T^3 \lfloor\frac{n}{T}\rfloor sum1(\lfloor\frac{n}{T}\rfloor) sum2(\lfloor\frac{n}{T}\rfloor)$

显然$\phi*\mu(T) T^3$是一个积性函数,我们可以把它线性筛出来

维护一下每个数的最小质因子及其最小质因子的指数就好了

后面显然可以分块,时间复杂度为$O(N+Tlog N)$

 code:

#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;

const int N=1e7+15;
const int mo=1ll<<30;
int cnt;
int prime[N],num[N],mi[N],f[N],sum[N];
bool vis[N];
inline int read()
{
    char ch=getchar();int s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
int qpow(int a,int b)
{
    int re=1;
    for (;b;b>>=1,a=a*a) if (b&1) re=re*a;
    return re;
}
ll phi(int p,int k)
{
    if (!k) return 1;
    return 1ll*qpow(p,k-1)*(p-1);
}
void pre()
{
    ll sum1=0,sum2=0;
    for (int i=1;i<N;i++)
    {
        sum1=(sum1+i)%mo;
        sum2=(sum2+1ll*i*i%mo)%mo;
        sum[i]=sum1*sum2%mo*i%mo;
    }
    f[1]=1;
    for (int i=2;i<N;i++)
    {    
        if (!vis[i])
        {
            prime[++cnt]=i;
            mi[i]=i;num[i]=1;
            f[i]=1ll*i*i%mo*i%mo*(i-2)%mo;
        }
        for (int j=1;j<=cnt&&prime[j]*i<N;j++)
        {    
            vis[i*prime[j]]=1;
            mi[i*prime[j]]=prime[j];
            if (mi[i]==prime[j]) num[i*prime[j]]=num[i]+1;
            else num[i*prime[j]]=1;
            if (i%prime[j]) f[i*prime[j]]=1ll*f[i]*f[prime[j]]%mo;
            else 
            {
                int q=qpow(prime[j],num[i*prime[j]]);
                f[q]=1ll*(phi(prime[j],num[i*prime[j]])-phi(prime[j],num[i*prime[j]]-1))*q%mo*q%mo*q%mo;
                f[i*prime[j]]=1ll*f[i*prime[j]/q]*f[q]%mo;
                break;
            }
        }
    }
    for (int i=1;i<N;i++) f[i]=1ll*(f[i-1]+f[i])%mo;
}
int main()
{
    pre();
    int T=read();
    while (T--)
    {
        int n=read();
        ll ans=0;
        for (int l=1,r;l<=n;l=r+1)
        {
            r=n/(n/l);
            (ans+=1ll*(f[r]-f[l-1])*sum[n/l]%mo)%mo;
        }
        printf("%lld\n",1ll*(ans+mo)%mo);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xxzh/p/10774284.html