Luogu P3327 - [SDOI2015] Sum of Approximate Numbers

Portal

Description

A total of \(T(T\leq5\times10^4)\) groups of data. Given \(n,m(n,m\leq5\times10^4)\) , find \[\sum_{i=1}^n\sum_{j=1}^m\sigma_0(ij)\]

Solution

First there is the conclusion: \(\sigma_0(xy)=\sum_{d_1|x}\sum_{d_2|y}[gcd(d_1,d_2)=1]\) . Let us first prove this conclusion.

Decompose \(x,y\) into prime factors to get \(x=\prod_{i=1}^kp_i^{a_i}\) , \(y=\prod_{i=1}^kp_i^{b_i} \) . Then if \(gcd(d_1,d_2)=1\) , it means that for a prime factor \(p_i\) , it only exists in \(d_1,d_2\) in zero or one. If it exists in \(d_1\) , there are \(a_i\) possibilities, if it exists in \(d_2\) , there are \(b_i\) possibilities, plus a total that does not exist \(a_i+b_i+1\) kinds. Then there are \(\prod_{i=1}^k(a_i+b_i+1)\) pairs of coprime \((d_1,d_2)\) , and this number is exactly equal to \(\sigma_0(xy)\) .

So it can be deduced normally.
\[\begin{align*} ans &= \sum_{i=1}^n \sum_{j=1}^m \sum_{d_1|i} \sum_{d_2|j}[gcd(d_1,d_2) =1] \\ &= \sum_{d_1=1}^{+∞} \sum_{d_2=1}^{+∞} \sum_{d_1|i}^n \sum_{d_2|j}^m [ gcd(d_1,d_2)=1] \\ &= \sum_{d_1=1}^{+∞} \sum_{d_2=1}^{+∞} ⌊\frac{n}{d_1}⌋ ⌊\frac {m}{d_2}⌋ \sum_{d_3|gcd(d_1,d_2)} \mu(d_3) \\ &= \sum_{d_3=1}^{+∞} \mu(d_3) \sum_{d_3| d_1} \sum_{d_3|d_2} ⌊\frac{n}{d_1}⌋ ⌊\frac{m}{d_2}⌋ \\ &= \sum_{d_3=1}^{+∞} \mu(d_3) \sum_{t_1=1}^{+∞} ⌊\frac{⌊\frac{n}{d_3}⌋}{t_1}⌋ \sum_{t_2=1}^{+∞} ⌊\frac{⌊\frac {m}{d_3}⌋}{t_2}⌋ \\ \end{align*}\] \(O(n\sqrt n)\) preprocessed \(f(x)=\sum_{i=1} ^x ⌊\dfrac{x}{i}⌋\) , there is \[ans=\sum_{d=1}^{+∞} \mu(d)f(⌊\dfrac{n}{d}⌋ )f(⌊\dfrac{m}{d}⌋)\] can be solved in \(O(\sqrt n)\) time.

Code

//[SDOI2015]约数个数和
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long lint;
inline char gc()
{
    static char now[1<<16],*s,*t;
    if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
    return *s++;
}
inline int read()
{
    int x=0; char ch=gc();
    while(ch<'0'||'9'<ch) ch=gc();
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x;
}
const int N=5e4+10;
int pCnt,pr[N]; bool pNot[N];
int mu[N],pre[N]; int f[N];
void init(int n)
{
    mu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!pNot[i]) pr[++pCnt]=i,mu[i]=-1;
        for(int j=1;j<=pCnt;j++)
        {
            int x=i*pr[j]; if(x>n) break;
            pNot[x]=true;
            if(i%pr[j]) mu[x]=-mu[i];
            else {mu[x]=0; break;}
        }
    }
    for(int i=1;i<=n;i++) pre[i]=pre[i-1]+mu[i];
    for(int x=1;x<=n;x++)
        for(int L=1,R;L<=x;L=R+1)
        {
            int v=x/L; R=x/v;
            f[x]+=(R-L+1)*v;
        }
}
int main()
{
    int task=read(); init(5e4);
    while(task--)
    {
        int n=read(),m=read();
        if(n>m) swap(n,m);
        lint ans=0;
        for(int L=1,R;L<=n;L=R+1)
        {
            int v1=n/L,v2=m/L; R=min(n/v1,m/v2);
            ans+=1LL*(pre[R]-pre[L-1])*f[v1]*f[v2];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325344559&siteId=291194637