51nod 1220 约数之和(杜教筛 + 推推推推推公式)

题意

给出\(n(1\leq n \leq 10^9)\),求\(\sum_{i=1}^n\sum_{j=1}^n\sigma(ij)\),其中\(\sigma(n)\)表示\(n\)的约数之和。

balabala

交了两道杜教筛的的板子题(51nod 1239, 1244)就看到了这题,然后不会搞,然后看题解看了一天一夜终于彻底搞明白一发A掉了。。。感觉学到了很多,写个博客整理一下,如有错请指出。

技能需求

数论函数与线性筛

莫比乌斯反演(也可以当成容斥去理解)

狄利克雷卷积

杜教筛

强大的数学推导功力(我没有)

先贴参考链接:

题目:http://www.51nod.com/Challenge/Problem.html#problemId=1220

这位这题的题解写的很好: https://www.cnblogs.com/hzoier/p/6937717.html

杜教筛:https://www.cnblogs.com/peng-ym/p/9446555.html 这位写的一看就懂

题解

推推推推推推推,我们记答案为\(Ans\)

1

我们一上来就需要用到一个公式,就是下面这个
\[
\sigma(ij)=\sum_{a|i}\sum_{b|j}[gcd(a,b)=1]\frac{aj}{b}
\]
感觉网上那群写博客的都是一眼就能看懂这是啥意思,但我却想了几个小时。。。所以我写详细一点

我们有\(\sigma(n)=\prod_{i=1}^k(p_i^0+p_i^1+...+p_i^{e_i})\),其中不同的\(p\)是出现在\(n\)的质因数分解式中不同的质因子,所以我们设\(i=p_1^{a_1}p_2^{a_2}...p_k^{a_k},j=p_1^{b_1}p_2^{b_2}...p_k^{b_k}(a,b\geq 0)\)

则\(\sigma(ij)=\prod_{m=1}^k(p_m^0+p_m^1+...+p_m^{a_m+b_m})\)

现在要想想上面那个公式的含义了,我们不妨考虑\(k=2\)的情况,假设我们选了\(a=p_1^{x_1},b=p_2^{x_2}\),这时\(gcd(a,b)=1\),那么当\(x_1\)从\(1\)往\(a_1\)增大时,\(x_2=0\),则\(\frac{aj}{b}\)中\(p_1\)的幂次范围是\(1+b_1\)到\(a_1+b_1\);反过来,当\(x_2\)从\(1\)往\(b_1\)增大时,\(x_1=0\),则\(\frac{aj}{b}\)中\(p_1\)的幂次范围是\(b_1-1\)到\(0\).再加上\(x_1=x_2=0\)的情况,我们正好不重不漏的选出了\(p_1\)的所有可能选择。

回头考虑\(\sigma(ij)=\prod_{m=1}^k(p_m^0+p_m^1+...+p_m^{a_m+b_m})\),如果我们把这\(k\)个因式乘出来,变成一个多项式,从这个多项式的角度的某一项去考虑,它有\((a_1+b_1)(a_2+b_2)...(a_k+b_k)\)种选择,选取多项式\(i\)的哪一项不会对选取多项式\(j\)产生任何影响,这就是它们”互相独立“的含义。

2

下面这一段主要思路就是不停的交换求和符号,把整除条件改成枚举条件以化简式子。举个例子,我们要计算下面这个式子:
\[
f(n)=\sum_{i=1}^n\sum_{j|i}i^2j
\\=\sum_{j=1}^n\sum_{j|i}i^2j
\\=\sum_{j=1}^n\sum_{a=1}^{\lfloor\frac{n}{j}\rfloor}(aj)^2j
\\=\sum_{i=1}^n\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}j^2i^3
\\=\sum_{i=1}^ni^3\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}j^2
\]
回到正题:
\[
Ans=\sum_{i=1}^n\sum_{j=1}^n\sum_{a|i}\sum_{b|j}[gcd(a,b)=1]\frac{aj}{b}
\\=\sum_{a=1}^n\sum_{b=1}^n\sum_{p=1}^{\lfloor\frac{n}{a}\rfloor}\sum_{q=1}^{\lfloor\frac{n}{b}\rfloor}[gcd(a,b)=1]\frac{aqb}{b}
\\=\sum_{a=1}^n\sum_{b=1}^n\sum_{i=1}^{\lfloor\frac{n}{a}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{b}\rfloor}[gcd(a,b)=1]aj
\\=\sum_{a=1}^na\sum_{b=1}^n[gcd(a,b)=1]\sum_{i=1}^{\lfloor\frac{n}{a}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{b}\rfloor}j
\\=\sum_{a=1}^na\lfloor\frac{n}{a}\rfloor\sum_{b=1}^n[gcd(a,b)=1]\frac{\lfloor\frac{n}{b}\rfloor(\lfloor\frac{n}{b}\rfloor+1)}{2}
\]
接下来还要搞的话只能在\([gcd(a,b) = 1]\)上做文章了

3

公式:\([gcd(a,b)=1]=\sum_{d=1}^{min(a,b)}\mu(d)[d|gcd(a,b)]\)

原理你可以当成莫比乌斯反演去搞,也可以当成容斥原理来想,(因为这两个本质上是一个东西----huchi)当\(gcd=1\)时,右边等于\(1\),当\(gcd>1\)时,以\(gcd=12=2^2*3\)为例,右边\(=\mu(1)+\mu(2)+\mu(3)+\mu(4)+\mu(6)+\mu(12)\),去掉为\(0\)的值,按质因数的个数分个组,\(=(\mu(1))+(\mu(2)+\mu(3))+(\mu(6))=C_2^01^0(-1)^2+C_2^11^1(-1)^1+C_2^21^2(-1)^0=(1-1)^2=0\)

以此类推,如果\(gcd\)有\(x\)个质因子那么就是\((1-1)^x\),这个公式是这么来的,如果需要严谨的证明的话我不会或许应该有人写过

4

继续。。
\[
Ans=\sum_{a=1}^na\lfloor\frac{n}{a}\rfloor\sum_{b=1}^n\frac{\lfloor\frac{n}{b}\rfloor(\lfloor\frac{n}{b}\rfloor+1)}{2}\sum_{d=1}^n\mu(d)[d|gcd(a,b)]
\]
老套路,继续交换求和符号,这次要连着\([d|gcd(a,b)]\)一起考虑。\(d|gcd(a,b)\)等价于\(d|a,d|b\).
\[
Ans=\sum_{d=1}^n\sum_{d|a}\sum_{d|b}a\lfloor\frac{n}{a}\rfloor\frac{\lfloor\frac{n}{b}\rfloor(\lfloor\frac{n}{b}\rfloor+1)}{2}\mu(d)
\\=\sum_{d=1}^n\sum_{p=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{q=1}^{\lfloor\frac{n}{d}\rfloor}pd\lfloor\frac{n}{pd}\rfloor\frac{\lfloor\frac{n}{pd}\rfloor(\lfloor\frac{n}{pd}\rfloor+1)}{2}\mu(d)
\\=\sum_{d=1}^nd\mu(d)\sum_{p=1}^{\lfloor\frac{n}{d}\rfloor}p\lfloor\frac{n}{pd}\rfloor\sum_{q=1}^{\lfloor\frac{n}{d}\rfloor}\frac{\lfloor\frac{n}{qd}\rfloor(\lfloor\frac{n}{qd}\rfloor+1)}{2}
\]
咦,后两个求和符号那两个式子好像是独立的,那就不妨设

\(f(n)=\sum_{i=1}^ni\lfloor\frac{n}{i}\rfloor\)

\(=\sum_{i=1}^n\sum_{j=1}^ni[i|j]\) 因为\(\lfloor\frac{n}{i}\rfloor\)意思就是\(1\)到\(n\)中\(i\)的倍数的个数。

\(=\sum_{j=1}^n\sum_{i=1}^ni[i|j]\)

\(=\sum_{j=1}^n\sigma(j)\).

\(g(n)=\sum_{i=1}^n\frac{\lfloor\frac{n}{i}\rfloor(\lfloor\frac{n}{i}\rfloor+1)}{2}\) 之前好像推出过这个东西,我们再把它变回去试试

\(=\sum_{i=1}^n\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}j\)

\(=\sum_{j=1}^n\sum_{i=1}^{\lfloor\frac{n}{j}\rfloor}j\)

\(=\sum_{j=1}^n\sum_{i=1}^{n}j[j|i]\)

\(=f(n)\).

我们把\(f(n)\)记成\(S_{\sigma}(n)\)吧.

因此有
\[
Ans=\sum_{d=1}^nd\mu(d)(S_{\sigma}(\lfloor\frac{n}{d}\rfloor))^2
\]

5

套杜教筛公式的时间到啦

\(\sigma\)是积性函数,可以线筛可以杜教筛,做法很多,我是卷上了个\(\mu\)得到\(id\)来筛的。

记\(f(d)=d\mu(d)\),\(f\)也是个积性函数,可以线筛可以杜教筛,卷上\(id\)得到\(e\),然后杜教筛起来就完事了。

最后求\(Ans\)的时候分块求,需要啥前缀和了就\(Calc\)啥,反正都是\(O(n^{\frac{2}{3}})\)我也不会分析

代码

\(main\)里是主分块,\(Calcmu\)是\(\mu\)的筛,\(Calcf\)是\(f\)的筛,\(Calcs\)是\(\sigma\)的筛

\(359ms\)

#include <bits/stdc++.h>
#define MAXN 1000000
#define LL long long
using namespace std;
const int Mx = 10000;
const int inv2 = 500000004;
const int mod = 1000000007;
LL gcd(LL a, LL b)
{
    return b?gcd(b,a%b):a;
}

int prime[MAXN + 8];
bool notprime[MAXN + 8];
int mu[MAXN + 8];
LL fsum[MAXN + 8], ssum[MAXN + 8], dsum[MAXN + 8];
int ind = 0;
void getprime()
{
    mu[1] = 1;
    ssum[1] = dsum[1] = 1;
    for (int i = 2; i <= MAXN; ++i)
    {
        if(!notprime[i])
        {
            prime[++ind] = i;
            mu[i] = -1;
            ssum[i] = dsum[i] = i + 1;
        }
        for (int j = 1; j <= ind && i * prime[j] <= MAXN; ++j)
        {
            notprime[i * prime[j]] = 1;
            if(i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                ssum[i * prime[j]] = ssum[i] / dsum[i] * (dsum[i] * prime[j] + 1); dsum[i * prime[j]] = dsum[i] * prime[j] + 1;
                break;
            }
            mu[i * prime[j]] = -mu[i];
            ssum[i * prime[j]] = ssum[i] * (1 + prime[j]); dsum[i * prime[j]] = 1 + prime[j];
        }
    }
    for (int i = 1; i <= MAXN; ++i)
    {
        fsum[i] = (fsum[i - 1] + i * mu[i] % mod + mod) % mod;
        ssum[i] = (ssum[i - 1] + ssum[i] % mod) % mod;
        mu[i] = (mu[i - 1] + mu[i] + mod) % mod;
    }
}
unordered_map<int,LL> _musum, _fsum, _ssum;

LL Calcmu(int n)
{
    if (n <= MAXN)
        return mu[n];
    auto it = _musum.find(n);
    if (it != _musum.end())
        return it->second;
    int last;
    LL ret = 1;
    for (int i = 2; i <= n; i = last + 1)
    {
        last = n / (n / i);
        ret = (ret - (1LL * last - i + 1) * Calcmu(n / i) % mod + mod) % mod;
    }
    return _musum[n] = ret;
}
LL Calcf(int n)
{
    if (n <= MAXN)
        return fsum[n];
    auto it = _fsum.find(n);
    if (it != _fsum.end())
        return it->second;
    int last;
    LL ret = 1;
    for (int i = 2; i <= n; i = last + 1)
    {
        last = n / (n / i);
        ret = (ret - ((1LL * last + i) % mod * (last - i + 1) % mod * inv2 % mod * Calcf(n / i) % mod) + mod) % mod;
    }
    return _fsum[n] = ret;
}

LL Calcs(int n)
{
    if (n <= MAXN)
        return ssum[n];
    auto it = _ssum.find(n);
    if (it != _ssum.end())
        return it->second;
    int last;
    LL ret = 1LL * n * (n + 1) % mod * inv2 % mod;
    for (int i = 2; i <= n; i = last + 1)
    {
        last = n / (n / i);
        ret = (ret - ((Calcmu(last) - Calcmu(i - 1) + mod) % mod * Calcs(n / i) % mod) + mod) % mod;
    }
    return _ssum[n] = ret;
}

int main()
{
    getprime();
    LL n, last;
    cin >> n;
    LL ans = 0;
    for (int i = 1; i <= n; i = last + 1)
    {
        last = n / (n / i);
        LL cc = Calcs(n / i);
        ans = (ans + (Calcf(last) - Calcf(i - 1) + mod) % mod * cc % mod * cc % mod) % mod;
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/zhugezy/p/11312301.html

时间: 2024-10-09 23:34:05

51nod 1220 约数之和(杜教筛 + 推推推推推公式)的相关文章

51nod 1220 约数之和

约数之和 Problem d(k)表示k的所有约数的和.d(6) = 1 + 2 + 3 + 6 = 12. 定义S(N) = ∑1<=i<=N ∑1<=j<=N d(i*j). 例如:S(3) = d(1) + d(2) + d(3) + d(2) + d(4) + d(6) + d(3) + d(6) + d(9) = 59,S(1000) = 563576517282. 给出正整数N,求S(N),由于结果可能会很大,输出Mod 1000000007(10^9 + 7)的结果.

【51nod-1239&amp;1244】欧拉函数之和&amp;莫比乌斯函数之和 杜教筛

题目链接: 1239:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 1244:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1244 杜教筛裸题,不过现在我也只会筛这俩前缀和... $$s(n)=\sum _{i=1}^{n}f(i)$$ 那么就有: $$\sum_{i=1}^{n}f(i)\lfloor \frac{n}{i} \

【51Nod 1237】最大公约数之和 V3 莫比乌斯反演+杜教筛

题意 求$\sum_{i=1}^{n}\sum_{j=1}^{n}(i,j)$ 枚举约数 $$ \begin{align} ans &=\sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}[(i,j)=d] \ &=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{n}{d} \rfloor}[(i,j)=1] \ \end{align} $$ 利用

51NOD 1237 最大公约数之和 V3(杜教筛)

题意 求 $\sum_{i=1}^n \sum_{j=1}^n gcd(i,j)$. 分析 $$\begin{aligned}\sum_{i=1}^n \sum_{j=1}^n gcd(i,j)  &= \sum_{i=1}^n \sum_{j=1}^n d[gcd(i, j)=d] \\&= \sum_{d=1}^n d \sum_{i=1}^n \sum_{j=1}^n[gcd(i,j=d)] \\&= \sum_{d=1}^n d \sum_{i=1}^{\left \lfl

51nod1238 最小公倍数之和 V3 莫比乌斯函数 杜教筛

题意:求\(\sum_{i = 1}^{n}\sum_{j = 1}^{n}lcm(i, j)\). 题解:因为是用的莫比乌斯函数求的,所以推导比大部分题解多...而且我写式子一般都比较详细,所以可能看上去很多式子,实际上是因为每一步都写了,几乎没有跳过的.所以应该都可以看懂的. 末尾的\(e\)函数是指的\(e[1] = 1\),\(e[x] = 0(x != 1)\)这样一个函数 \[\sum_{i = 1}^{n}\sum_{j = 1}^{n}lcm(i, j)\] \[\sum_{i

HDU6706 CCPC 2019网络赛 huntian oy 推式子+杜教筛

CCPC 2019 网络赛 HDU 6706 huntian oy 标签 奇奇怪怪的数论结论 杜教筛 前言 我的csdn和博客园是同步的,欢迎来访danzh-博客园~ 简明题意 给定n,a,b,求: \[\sum_{i=1}^n\sum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\%(10^9+7)\] 思路 首先有一个结论: \[gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)}-j^{gcd(a,b)}\] 上面的结论对于i,j互质是成立的

杜教筛 学习总结

看了看唐老师的blog,照猫画虎的做了几道题目,感觉对杜教筛有些感觉了 但是稍微有一点难度的题目还是做不出来,放假的时候争取都A掉(挖坑ing) 这篇文章以后等我A掉那些题目之后再UPD上去就好啦 由于懒得去写怎么用编辑器写公式,所以公式就准备直接copy唐老师的啦 首先积性函数和完全积性函数什么的就不再多说了 列举常见的积性函数: 1.约数个数函数和约数个数和函数 2.欧拉函数phi 3.莫比乌斯函数mu 4.元函数e 其中e(n)=[n==1] 5.恒等函数I 其中I(n)=1 6.单位函数

数论入门——莫比乌斯函数,欧拉函数,狄利克雷卷积,线性筛,莫比乌斯反演,杜教筛

一个菜鸡对数论的一点点理解... 莫比乌斯函数 定义函数\(\mu(n)\)为: 当n有平方因子时,\(\mu(n)=0\). 当n没有平方因子时,\(\mu(n)=(-1)^{\omega(n)}\),\(\omega(n)\)表示n不同质因子的个数. 性质1: \(\sum_{d|n}\mu(d)=[n=1]\) 证明:我们把n分解质因数,则原式\(=(-1+1)^{\omega(n)}=0\). 因为对于不同的质因子,只有选和不选两种方案,这是一个组合数相加的形式,偶数加奇数减,根据二项式

【数论】狄利克雷卷积及其快速计算方法及杜教筛

目录(假的 狄利克雷卷积基础知识 数论函数 狄利克雷卷积定义 狄利克雷卷积性质 常用卷积 卷积计算方法 最暴力的暴力 稍好的暴力 优美的暴力 莫比乌斯反演(待填坑) 杜教筛 经典杜教筛 第二种杜教筛 第三种杜教筛 背景 本人即将去CTS&APIO2019,由于一些特殊原因,发现自己数论突然变得很菜. 就决定在去的前一天,翻出来以前的数论学习资料看一看.翻到了czgj的校内狄利克雷卷积课件,发现其中提到了的任意数列\(f(n)\)和\(g(n)\)的狄利克雷卷积\((f*g)(n)\)(从1到n,