Luogu P2257 YY的GCD

莫比乌斯反演第一题。莫比乌斯反演入门

数论题不多BB,直接推导吧。

首先,发现题目所求\(ans=\sum_{i=1}^n\sum_{j=1}^m [\gcd(i,j)=prime]\)

考虑反演,我们令\(f(d)\)\(\gcd(i,j)(i\in[1,n],j\in[1,m])=d\)的个数,\(F(n)\)\(d|\gcd(i,j)\)的个数

即:

\[f(d)=\sum_{i=1}^n\sum_{j=1}^m [\gcd(i,j)=d] \]

\[F(s)=\sum_{s|d}f(d)=\lfloor\frac{n}{s} \rfloor \lfloor\frac{m}{s} \rfloor \]

根据莫比乌斯反演定理,有:

\[f(n)=\sum_{n|d} \mu(\lfloor\frac{d}{n} \rfloor)F(d) \]

所以开始化简,原式:

\[ans=\sum_{p\in prime} \sum_{i=1}^n \sum_{j=1}^m[\gcd(i,j)=p] \]

后面那个就是我们设的\(f(p)\),所以我们带入得:

\[ans=\sum_{p\in prime} f(p) \]

用上面的公式反演一下:

\[ans=\sum_{p\in prime} \sum_{p|d}\mu(\lfloor\frac{d}{p} \rfloor)F(d) \]

这个不好处理,我们考虑把枚举\(p\)变成枚举\(\lfloor\frac{d}{p} \rfloor\),则有:

\[ans=\sum_{p\in prime} \sum_{d=1}^{\min(\lfloor\frac{n}{p} \rfloor,\lfloor\frac{m}{p} \rfloor)}\mu(d)F(d\cdot p) \]

再根据\(F(s)\)的性质代进去就有:

\[ans=\sum_{p\in prime} \sum_{d=1}^{\min(\lfloor\frac{n}{p} \rfloor,\lfloor\frac{m}{p} \rfloor)}\mu(d)\lfloor\frac{n}{d\cdot p} \rfloor\lfloor\frac{m}{d\cdot p} \rfloor \]

然后我们用\(T\)换掉\(d\cdot p\),则有:

\[ans=\sum_{T=1}^{\min(n,m)} \sum_{p|T,p\in prime} \mu(\lfloor\frac{T}{p} \rfloor)\lfloor\frac{n}{T} \rfloor\lfloor\frac{m}{T} \rfloor \]

\(\lfloor\frac{n}{T} \rfloor\lfloor\frac{m}{T} \rfloor\)提到前面来就有:

\[ans=\sum_{T=1}^{\min(n,m)} \lfloor\frac{n}{T} \rfloor\lfloor\frac{m}{T} \rfloor\sum_{p|T,p\in prime} \mu(\lfloor\frac{T}{p} \rfloor) \]

然后我们发现这个式子就是\(O(n)\)的了,一看题目,多组询问!

结果还是套路,看到那个\(\lfloor\frac{n}{T} \rfloor\lfloor\frac{m}{T} \rfloor\)发现可以除法分块搞。

后面的式子稍加分析可以发现在筛法结束后枚举每个素数,再枚举\(\lfloor\frac{T}{p} \rfloor\)来统计。最后做一个前缀和即可。

CODE

#include<cstdio>
#include<cctype>
#define RI register int
using namespace std;
const int P=10000000;
int t,n,m,prime[P+5],cnt,miu[P+5]; long long sum[P+5],ans; bool vis[P+5];
class FileInputOutput
{
    private:
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        #define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
        #define S 1<<21
        char Fin[S],Fout[S],*A,*B; int Ftop,pt[25];
    public:
        FileInputOutput() { A=B=Fin; Ftop=0; } 
        inline void read(int &x)
        {
            x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1;
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc())); x*=flag;
        }
        inline void write(long long x)
        {
            if (!x) return (void)(pc(48),pc('\n')); RI ptop=0;
            while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');
        }
        inline void Fend(void)
        {
            fwrite(Fout,1,Ftop,stdout);
        }
        #undef tc
        #undef pc
        #undef S
}F;
#define Pi prime[j]
inline void Euler(void)
{
    vis[1]=miu[1]=1; RI i,j; for (i=2;i<=P;++i)
    {
        if (!vis[i]) prime[++cnt]=i,miu[i]=-1;
        for (j=1;j<=cnt&&i*Pi<=P;++j)
        {
            vis[i*Pi]=1; if (i%Pi) miu[i*Pi]=-miu[i]; else break;
        }
    }
    for (j=1;j<=cnt;++j) for (i=1;i*Pi<=P;++i) sum[i*Pi]+=miu[i];
    for (i=1;i<=P;++i) sum[i]+=sum[i-1];
}
#undef Pi
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline void swap(int &a,int &b)
{
    int t=a; a=b; b=t;
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    for (Euler(),F.read(t);t;--t)
    {
        F.read(n); F.read(m); ans=0; if (n>m) swap(n,m);
        for (RI l=1,r;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l)); ans+=1LL*(n/l)*(m/l)*(sum[r]-sum[l-1]);
        }
        F.write(ans);
    }
    return F.Fend(),0;
}
posted @ 2018-10-25 19:34  空気力学の詩  阅读(334)  评论(0编辑  收藏  举报