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

 

 

大致题意:计算和式

                                                               \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 <bits/stdc++.h>
#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<<": "<<x<<endl
using namespace std;
using std::default_random_engine;

const int N = 1e7 + 10;
const int mod = 998244353;

int phi[N],phisum[N],q[N],p[N],sz;
bool isp[N];

typedef __int128 int128;

void init()
{
    int sz=0;
    phi[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!isp[i])p[++sz]=i,phi[i]=i-1;
         for(int j=1;j<=sz&&(LL)i*p[j]<N;j++)
         {
            isp[i*p[j]]=1;
            if(i%p[j]==0)
            {
                phi[p[j]*i]=phi[i]*p[j];
                break;
            } else phi[p[j]*i]=(p[j]-1)*phi[i];
        }
    }
    for(int i=1;i<N;i++)
    {
        phisum[i]=(phisum[i-1]+phi[i])%mod;
        q[i]=(q[i-1]+(LL)phi[i]*i%mod)%mod;
    }
}

LL qpow(LL x,LL n)
{
    LL res=1;
    while(n)
    {
        if (n&1) res=res*x%mod;
        x=x*x%mod; n>>=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 <class T>
    Istream &operator >>(T &x) {
        static char ch;static bool neg;
        for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
        for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
        x=neg?-x:x;
        return *this;
    }
}fin;

struct Ostream {
    template <class T>
    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<<ans<<'\n';
    }

    return 0;
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值