数论分块

数论分块

对于一类含有\(\lfloor \frac{𝑛}{i} \rfloor\)的求和式 (𝑛 为常数),由于\(\lfloor \frac{𝑛}{i} \rfloor\)单调不增,故存在多个区间[𝑙,𝑟], 使得\(\lfloor \frac{𝑛}{i} \rfloor\)=\(\lfloor \frac{𝑛}{j} \rfloor\) (𝑖,𝑗∈[𝑙,𝑟]) 成立。

对于任意一个𝑖,最大的满足上式的 𝑗=\(\lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor\)

\(\\\)
\(\\\)
\(\\\)
\(\\\)

证明

\(\lfloor \frac{𝑛}{i} \rfloor \leqslant\frac{𝑛}{i}\)
\(\Rightarrow \lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor \geqslant \lfloor {\frac{n}{ \frac{𝑛}{i} } }\rfloor =\lfloor i \rfloor=i\)
\(\Rightarrow i \leqslant \lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} } \rfloor \)

\(j= \lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor\)

\(\\\)
\(\\\)
\(\\\)
\(\\\)

例题

经典题 P1403 [AHOI2005]约数研究

题意:
\(f(x)\)表示x的约数个数,求\(\sum_{i=1}^nf(i)\)
思路:
对于\(i\),在\(1~n\)中,他的倍数有\(\lfloor \frac{𝑛}{i} \rfloor\)个,因此\(1~n\)中共有个以\(i\)为约数的数。
因此\(\sum_{i=1}^nf(i)=\sum_{i=1}^n\lfloor \frac{𝑛}{i} \rfloor\)

现在考虑数论分块
对于每一个l∈[1,n],存在区间[l,r],\(r=\lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor\)
使得\(\lfloor \frac{𝑛}{i} \rfloor\)=\(\lfloor \frac{𝑛}{j} \rfloor\)
区间贡献\((r-l+1)\times \lfloor \frac{𝑛}{i} \rfloor\).
\(O(2\sqrt n)\)

int n;
signed main()
{
    n=rd;
    int ans=0;
    for(int i=1,j=1;i<=n;i=j+1)
    {
        j=n/(n/i);
        ans+=(j-i+1)*(n/i);
    }
    printf("%lld\n",ans);
    return 0;
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

[CQOI2007]余数求和

思路:

\[\sum_{i=1}^{n} k\ mod \quad i=\sum_{i=1}^{n} (k-\lfloor \frac{k}{i} \rfloor \times i) \]

int k,n;
signed main()
{
    n=rd,k=rd;
    int ans=n*k;
    for(int i=1,j=1;i<=n;i=j+1)
    {
        if(k/i==0) break;
        j=min(n,k/(k/i));
        ans-=(k/i)*(j+i)*(j-i+1)/2;
    }
    printf("%lld\n",ans);
    return 0;
}

\(\\\)
\(\\\)
\(\\\)
\(\\\)

P2424 约数和

int x,y;
int f(int a)
{
    int ans=0;
    for(int i=1,j=1;i<=a;i=j+1)
    {
        j=a/(a/i);
        ans+=(a/i)*(i+j)*(j-i+1)/2;
    }
    return ans;
}
signed main()
{
    x=rd,y=rd;
    printf("%lld\n",f(y)-f(x-1));
    return 0;
}
posted @ 2021-11-15 18:15  juuich  阅读(29)  评论(0编辑  收藏  举报