2019HDU多校赛 第一场 K HDU 6588 Function(莫比乌斯反演)

2019HDU多校赛 第一场 K HDU 6588 Function(莫比乌斯反演)_第1张图片

2019HDU多校赛 第一场 K HDU 6588 Function(莫比乌斯反演)_第2张图片

 

 

大致题意:计算和式

                                                               \sum_{i=1}^n\gcd(\lfloor{\sqrt[3]{i}}\rfloor,i)\mod 998244353

显然是一个道反演的题目,话不多说直接开始推导吧。首先把式子拆成两个求和部分:

                                      \sum_{a=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\sum_{i=a^3}^{(a+1)^3-1}\gcd(a,i) + \sum_{i=\lfloor{\sqrt[3]{n}}\rfloor^3}^{n}\gcd(\lfloor{\sqrt[3]{n}}\rfloor,i)\mod 998244353

然后你会发现前后两个式子都是\sum_{i=l}^{r}\gcd(a,i)的形式,于是我们考虑这个式子怎么计算。

                                          \begin{align*} \sum_{i=l}^{r}\gcd(a,i)&=\sum_{x|a}x\sum_{i=l}^{r}[\gcd(a,i)==x] \\ &=\sum_{x|a}x\sum_{x|d,d|a}\mu{(\frac{d}{x})}(\lfloor\frac{r}{d}\rfloor-\lfloor\frac{l-1}{d}\rfloor) \\ &=\sum_{d|a}(\lfloor\frac{r}{d}\rfloor-\lfloor\frac{l-1}{d}\rfloor)\sum_{x|d}x\mu{(\frac{d}{x})} \\ &=\sum_{d|a}(\lfloor\frac{r}{d}\rfloor-\lfloor\frac{l-1}{d}\rfloor)\phi(d) \end{align*}

如此,你会发现,对于一个固定的a,我们可以在O(\sqrt{a})的时间内算出来。因此,对于和式的第二部分,我们可以在O(\lfloor\sqrt[6]{n}\rfloor)的时间内求出来。现在,我们考虑前面那个部分怎么求

     \begin{align*}\sum_{a=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\sum_{i=a^3}^{(a+1)^3-1}\gcd(a,i) &=\sum_{a=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\sum_{d|a}(\lfloor\frac{(a+1)^3-1}{d}\rfloor-\lfloor\frac{a^3-1}{d}\rfloor)\phi(d) \\&=\sum_{d=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\phi(d) \sum_{x=1}^{\lfloor\frac{\lfloor{\sqrt[3]{n}}\rfloor-1}{d}\rfloor}(\lfloor\frac{(xd+1)^3-1}{d}\rfloor-\lfloor\frac{(xd)^3-1}{d}\rfloor) \\&= \sum_{d=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\phi(d)\sum_{x=1}^{\lfloor\frac{\lfloor{\sqrt[3]{n}}\rfloor-1}{d}\rfloor}3x^2d+3x+1 \\&=\sum_{d=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\phi(d)d\lfloor\frac{y(y+1)(2y+1)}{6}\rfloor+\sum_{d=1}^{\lfloor{\sqrt[3]{n}}\rfloor-1}\phi(d)(\lfloor\frac{y(y+1)}{2}\rfloor+y) \\&(y=\lfloor\frac{\lfloor{\sqrt[3]{n}}\rfloor-1}{d}\rfloor) \end{align*}

然后我们发现,由于y是一个分式而且是向下取整,所以显然我们可以用数论分块一次求一个区间的值。因此在预处理\sum\phi(i)\sum\phi(i)i 的情况下,我们可以在O(\lfloor\sqrt[6]{n}\rfloor)的时间复杂度内求出答案。这样总的时间复杂度就是O(\lfloor\sqrt[3]{n}\rfloor)预处理时的复杂度,单次询问复杂度为O(\lfloor\sqrt[6]{n}\rfloor)。最后记得要使用__int128保存输入,具体见代码:

#include 
#define LL long long
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define file(x) freopen(#x".in","w",stdout);
#define bug(x) cerr<<#x<<": "<>=1;
    }
    return res;
}

int128 getnn(int128 nn)
{
    int128 l=0,r=1e9,mid,res;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if ((int128)mid*mid*mid<=nn) res=mid,l=mid+1;
                                        else r=mid-1;
    }
    return res;
}

struct Istream {
    template 
    Istream &operator >>(T &x) {
        static char ch;static bool neg;
        for(ch=neg=0;ch<'0' || '9'
    Ostream &operator <<(T x) {
        x<0 && (putchar('-'),x=-x);
        static char stack[233];static int top;
        for(top=0;x;stack[++top]=x%10+'0',x/=10);
        for(top==0 && (stack[top=1]='0');top;putchar(stack[top--]));
        return *this;
    }

    Ostream &operator <<(char ch) {
        putchar(ch);
        return *this;
    }
}fout;

int main()
{
    init();
    LL inv2=qpow(2,mod-2);
    int T_T; fin>>T_T;
    while(T_T--)
    {
        int128 n,m,nn;
        int t,ans=0;
        fin>>n; nn=getnn(n); m=nn*nn*nn;
        for(int i=1;i*i<=nn;i++)
        {
            if (nn%i) continue;
            ans=(ans+(n/i-(m-1)/i)%mod*phi[i]%mod)%mod;
            if (i*i!=nn)
                t=nn/i,ans=(ans+(n/t-(m-1)/t)%mod*phi[t]%mod)%mod;
        }
        --nn;
        for(int l=1,r;l<=nn;l=r+1)
        {
            t=nn/l; r=nn/t;
            LL tmp1=(q[r]-q[l-1]+mod)%mod;
            LL tmp2=(phisum[r]-phisum[l-1]+mod)%mod;
            ans=(ans+tmp1*inv2%mod*t%mod*(t+1)%mod*(2*t+1)%mod)%mod;
            ans=((ans+tmp2*(t+1)%mod*t%mod*inv2%mod*3%mod)%mod+t*tmp2%mod)%mod;
        }
        assert(ans>=0);
        fout<

 

你可能感兴趣的:(---------Online,Judge--------,HDU,数论,欧拉/莫比乌斯,2019HDU多校赛)