51nod 1575 Gcd and Lcm

51nod 1575 Gcd and Lcm

链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1575

这个题目。完美的体现了洲阁筛更为通用。。。。

题目要就计算:
i=1nj=1ik=1ilcm(gcd(i,j),gcd(i,k))

F(n) 有:

F(n)=i=1nj=1nlcm(gcd(i,n),gcd(j,n))=a|nb|ni=1nj=1nabgcd(a,b)[gcd(i,n)=a][gcd(j,n)=b]=a|nb|nabgcd(a,b)i=1naj=1nb[in][jn]=a|nb|nabgcd(a,b)φ(na)φ(nb)=d|n1da|nb|nabφ(na)φ(nb)[gcd(a,b)=d]=d|ndandbndabφ(nad)φ(nbd)[ab]=d|nnda|db|dabφ(da)φ(db)[ab]

令:
g(n)=g(n,1)g(n,k)=a|nb|nabφ(na)φ(nb)[gcd(a,b)=k]

令:
G(n,k)=[k|n]k|dg(n,d)=[k|n]k2ankbnkabφ(nka)φ(nkb)

反演有:
g(n)=g(n,1)=d1μ(d)d2andbndabφ(nda)φ(ndb)[d|n]=d|nμ(nd)(nd)2a|db|dabφ(da)φ(db)=d|nμ(nd)(nd)2(a|daφ(da))2

因为积性函数的狄利克雷积依然为积性函数。所以 g(n) 为积性函数。

因为 F=Ng

所以 F 为积性函数:
F(Pk)=d|PkPkda|db|dabφ(da)φ(db)[ab]=x=0kPkxi=0xj=0xPi+jφ(Pxi)φ(Pxj)[PiPj]=x=0kPkx(2φ(Px)j=0x1Pjφ(Pxj)φ2(Px)+2Pxφ(Px))=x=0kPkx(2xφ2(Px)φ2(Px)+2Pxφ(Px))=Pk+x=1kPkx((2x1)(PxPx1)2+2Px(PxPx1))=Pk+(PkPk1)x=1k((2x1)(PxPx1)+2Px)

其中:
x=1k(2x1)(PxPx1)=x=1k(2x1)Pxx=1k(2x1)Px1=x=1k(2x1)Pxx=0k1(2x+1)Px=2x=1k1Px1+(2k1)Pk

所以:
Pk+(PkPk1)x=1k((2x1)(PxPx1)+2Px)=Pk+(PkPk1)(2x=1k1Px1+(2k1)Pk+2x=1kPx)=Pk+(PkPk1)(2Pk+(2k1)Pk1)=2(k+1)(P2kP2k1)+Pk1

所以:
F(Pk)=(2k+1)(P2kP2k1)+Pk1

特别的:
F(1)=1

洲阁筛计算之

#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <cmath>
#define MAXN 1000000
#define SQR 40000
using namespace std;
typedef unsigned int uint;
const uint INF=0x3f3f3f3f;

uint C0[SQR];
uint _C0[SQR];
uint C1[SQR];
uint _C1[SQR];
uint C2[SQR];
uint _C2[SQR];
uint prim[SQR];
uint pa0[SQR];
uint pa1[SQR];
uint pa2[SQR];
uint F[SQR];
uint _F[SQR];
uint tmp[SQR];
uint Sf[SQR];
uint pf[SQR][32];
bool vis[SQR];
uint S1(uint n)
{
    if(n&1)return n*((n+1)>>1);
    return (n>>1)*(n+1);
}
uint S2(uint n)
{
    uint n1=n+1,n2=2*n+1;
    if(n&1)n1>>=1;
    else n>>=1;

    if(n%3==0)n/=3;
    else
    {
        if(n2%3==0)
            n2/=3;
        else
            n1/=3;
    }
    return n*n1*n2;
}
uint Pow(uint a,uint b)
{
    uint tmp=1;
    while(b)
    {
        if(b&1)
            tmp*=a;
        a*=a;
        b>>=1;
    }
    return tmp;
}
uint f(uint P,uint c)
{
    return (2*c+1)*(Pow(P,c<<1)-Pow(P,(c<<1)-1))+Pow(P,c-1);
}
uint gcd(uint a,uint b)
{
    if(b==0)return a;
    return gcd(b,a%b);
}
uint FF(uint a,uint b,uint c)
{
    uint A=gcd(a,b);
    uint B=gcd(a,c);
    return A*B/gcd(A,B);
}
int main ()
{
    for(uint i=2;i<SQR;i++)
    {
        pa0[i]=pa0[i-1];
        pa1[i]=pa1[i-1];
        pa2[i]=pa2[i-1];
        Sf[i]=Sf[i-1];
        if(vis[i])continue;
        prim[++pa0[i]]=i;
        pa1[i]+=i;
        pa2[i]+=i*i;
        Sf[i]+=f(i,1);
        for(uint j=1;j<31;j++) pf[i][j]=f(i,j);
        for(uint j=i<<1;j<SQR;j+=i)vis[j]=true;
    }
    uint n,T;
    scanf("%u",&T);
    while(T--)
    {
        scanf("%u",&n);
        uint m=sqrt(n)+1,V=pow(n,0.25)+1;
        for(uint i=1;i<m;i++)
        {
            C0[i]=i;
            _C0[i]=n/i;
            C1[i]=C1[i-1]+i;
            _C1[i]=S1(n/i);
            C2[i]=C2[i-1]+i*i;
            _C2[i]=S2(n/i);
        }
        uint k=1;
        while(prim[k]<V)
        {
            uint P=prim[k];
            for(uint i=1;i<m;i++)
            {
                uint t=i*prim[k];
                uint u=n/t;
                if(u<m)
                {
                    _C0[i]-=C0[u];
                    _C1[i]-=C1[u]*P;
                    _C2[i]-=C2[u]*P*P;
                }
                else
                {
                    _C0[i]-=_C0[t];
                    _C1[i]-=_C1[t]*P;
                    _C2[i]-=_C2[t]*P*P;
                }
            }
            for(uint i=m-1;i;i--)
            {
                C0[i]-=C0[i/P];
                C1[i]-=C1[i/P]*P;
                C2[i]-=C2[i/P]*P*P;
            }
            k++;
        }
        memset(tmp,0x3f,sizeof tmp);
        uint fir,lim=m;
        while(prim[k]<m)
        {
            uint P=prim[k];
            fir=lim;
            lim=1+n/(prim[k]*prim[k]);
            for(uint i=1;i<lim;i++)
            {
                uint t=P*i;
                uint u=n/t;
                if(u<m)
                {
                   if(u<prim[k])
                   {
                       _C0[i]-=1;
                       _C1[i]-=P;
                       _C2[i]-=P*P;
                   }
                   else
                   {
                       _C0[i]-=pa0[u]-k+2;
                       _C1[i]-=(pa1[u]-pa1[prim[k-1]]+1)*P;
                       _C2[i]-=(pa2[u]-pa2[prim[k-1]]+1)*P*P;
                   }
                }
                else
                {
                    if(tmp[t]<INF)
                    {
                        _C0[i]-=_C0[t]-(k-tmp[t]);
                        _C1[i]-=P*(_C1[t]-(pa1[prim[k-1]]-pa1[prim[tmp[t]-1]]));
                        _C2[i]-=P*P*(_C2[t]-(pa2[prim[k-1]]-pa2[prim[tmp[t]-1]]));
                    }
                    else
                    {
                        _C0[i]-=_C0[t];
                        _C1[i]-=_C1[t]*P;
                        _C2[i]-=_C2[t]*P*P;
                    }
                }
            }
            for(uint i=lim;i<fir;i++)tmp[i]=k;
            k++;
        }
        for(uint i=1;i<m;i++)
        {
            if(tmp[i]==INF)continue;
            _C0[i]-=k-tmp[i];
            _C1[i]-=pa1[prim[k-1]]-pa1[prim[tmp[i]-1]];
            _C2[i]-=pa2[prim[k-1]]-pa2[prim[tmp[i]-1]];
        }
        for(uint i=1;i<m;i++)
            _F[i]=3*(_C2[i]-_C1[i])+_C0[i];
        k--;
        V--;
        uint X=prim[k];
        memset(vis,0,sizeof vis);
        while(prim[k]>V)
        {
            uint P=prim[k];
            uint bf;
            lim=n/(P*P)+1;
            for(uint i=1;i<lim;i++)
            {
                uint t=i,c=0;
                while(t<=n/P)
                {
                    c++;
                    t*=P;
                    bf=pf[P][c];
                    uint u=n/t;
                    if(u<m)
                    {
                        if(u<prim[k])
                            _F[i]+=bf;
                        else
                            _F[i]+=(Sf[u]-Sf[prim[k]]+1)*bf;
                    }
                    else
                    {
                        if(!vis[t])
                            _F[i]+=bf*(_F[t]+Sf[X]-Sf[prim[k]]);
                        else
                            _F[i]+=bf*_F[t];
                    }
                }
                if(!vis[i])
                {
                    _F[i]+=Sf[X]-Sf[prim[k]];
                    vis[i]=true;
                }
            }
            k--;
        }

        for(uint i=lim;i<m;i++)_F[i]+=Sf[X]-Sf[prim[k]];
        for(uint i=1;i<m;i++)
        {
            if(i<=V)
                F[i]=1;
            else
                F[i]=Sf[i]-Sf[prim[k]]+1;
        }
        while(k)
        {
            uint P=prim[k];
            for(uint i=1;i<m;i++)
            {
                uint d=i,c=0;
                while(d<=n/P)
                {
                    d*=P;
                    c++;
                    uint u=n/d;
                    if(u<m)
                        _F[i]+=F[u]*pf[P][c];
                    else
                        _F[i]+=_F[d]*pf[P][c];
                }
            }

            for(uint i=m-1;i;i--)
            {
                uint d=1,c=0;
                while(d*P<=i)
                {
                    d*=P;
                    c++;
                    F[i]+=F[i/d]*pf[P][c];
                }
            }
            k--;
        }
        printf("%u\n",_F[1]);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值