luogu3327 [SDOI2015]约数个数和

link

设\(d(x)\)表示x约数个数,给定n,m,\(\sum_{i=1}^n\sum_{j=1}^md(ij)\)

多组询问,1<=T<=50000,1<=N, M<=50000

前置知识:\(d(ij)=\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]\)

证明:\(xy\)一定是\(ij\)的约数。考虑一个质数\(p\),\(i\)中包含\(p^a\),\(j\)中包含\(p^b\),则\(ij\)中包含的是\(p^{a+b}\)。若\(\gcd(x,y)=1\),说明\(x,y\)中至少有一个数的\(p^k\)为1,容斥一下就有\(a+b+1\)种,而\(p^{a+b}\)中也恰好有\(a+b+1\)的贡献。最后把所有质数贡献乘起来就是答案。

推式子即可:

\(\sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]\)

\(=\sum_{x=1}^n\sum_{y=1}^m\lfloor\frac nx\rfloor\lfloor\frac my\rfloor[\gcd(x,y)=1]\)

\(=\sum_{x=1}^n\sum_{y=1}^m\lfloor\frac nx\rfloor\lfloor\frac my\rfloor\sum_{d|x,d|y}\mu(d)\)

\(=\sum_{d=1}^n\mu(d)\sum_{x=1}^{n/d}\sum_{y=1}^{m/d}\lfloor\frac n{xd}\rfloor\lfloor\frac m{yd}\rfloor\)

设\(f(n)=\sum_{i=1}^n\lfloor\frac ni\rfloor=\sum_{i=1}^nd(i)\),这里的\(d\)是约数个数,由于\(n\le50000\),这个可以预处理线性筛约数个数

则原式=\(\sum_{d=1}^n\mu(d)f(\lfloor\frac nd\rfloor)f(\lfloor\frac md\rfloor)\),直接上数论分块


#include <cstdio>
#include <functional>
using namespace std;

int prime[50010], fuck = 50000, tot, d[50010], d1[50010], mu[50010];
bool vis[50010];

int main()
{
    mu[1] = d[1] = d1[1] = 1;
    for (int i = 2; i <= fuck; i++)
    {
        if (vis[i] == false) { prime[++tot] = i, mu[i] = -1, d[i] = d1[i] = 2; }
        for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
        {
            vis[i * prime[j]] = true;
            if (i % prime[j] == 0)
            {
                d1[i * prime[j]] = d1[i] + 1;
                d[i * prime[j]] = d[i] / d1[i] * d1[i * prime[j]];
                break;
            }
            d1[i * prime[j]] = 2;
            d[i * prime[j]] = d[i] * 2;
            mu[i * prime[j]] = -mu[i];
        }
        d[i] += d[i - 1];
        mu[i] += mu[i - 1];
    }
    int t; scanf("%d", &t);
    while (t --> 0)
    {
        int n, m;
        long long ans = 0;
        scanf("%d%d", &n, &m);
        if (n > m) swap(n, m);
        for (int i = 1, j; i <= n; i = j + 1)
        {
            j = min(n / (n / i), m / (m / i));
            ans += (mu[j] - mu[i - 1]) * (long long)d[n / i] * d[m / i];
        }
        printf("%lld\n", ans);
    }
    return 0;
}

45行一遍AC

最近做数论题都不用观察题解了。。。

原文地址:https://www.cnblogs.com/oier/p/10298932.html

时间: 2024-10-03 14:45:11

luogu3327 [SDOI2015]约数个数和的相关文章

BZOJ 3994: [SDOI2015]约数个数和

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 898  Solved: 619[Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

【BZOJ 3994】3994: [SDOI2015]约数个数和(莫比乌斯反演)

3994: [SDOI2015]约数个数和 Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7 4 5 6 Sample Output 110 121 HINT 1<=N, M<=50000 1<=T<=50000 Source Round 1 感谢yts199

3994: [SDOI2015]约数个数和

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 858  Solved: 587[Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

BZOJ 3994 [SDOI2015]约数个数和 (神定理+莫比乌斯反演)

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit:128 MB Submit: 239  Solved: 176 [Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

[SDOI2015] 约数个数和 (莫比乌斯反演)

[SDOI2015]约数个数和 题目描述 设d(x)为x的约数个数,给定N.M,求 \(\sum^N_{i=1}\sum^M_{j=1}d(ij)\) 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行,一个整数T,表示测试数据的组数.接下来的T行,每行两个整数N.M. 输出格式: T行,每行一个整数,表示你所求的答案. 输入输出样例 输入样例#1: 2 7 4 5 6 输出样例#1: 110 121 说明 \(1<=N, M<=50000\) \(1<=T<=50000\

[BZOI 3994] [SDOI2015]约数个数和

[BZOI 3994] [SDOI2015]约数个数和 题面 设d(x)为x的约数个数,给定N.M,求\(\sum _{i=1}^n \sum_{i=1}^m d(i \times j)\) T组询问,\(N,M,T \leq 50000\) 分析 首先有一个结论 \[d(nm)= \sum _{i |n} \sum _{j|m} [gcd(i,j)=1]\] 这是因为nm的约数都可以表示为\(i \times \frac{m}{j}\)的形式,并且为了不重复算,要保证\(gcd(i,j)=1\

【bzoj3994】[SDOI2015]约数个数和 莫比乌斯反演

题目描述 设d(x)为x的约数个数,给定N.M,求   输入 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. 输出 T行,每行一个整数,表示你所求的答案. 样例输入 2 7 4 5 6 样例输出 110 121 题解 莫比乌斯反演 根据 bzoj4176 推出的结论, 那么就有: 预处理mu及其前缀和. 由于要处理多组询问,所以需要用O(n√n)的时间预处理出f,然后对于每组询问分块来求. #include <cstdio> #incl

Sdoi2015约数个数和题解莫比乌斯反演

题目描述 T组数据,求ΣNi=1ΣMj=1d(ij),d(x)代表x的约数个数. 1≤N,M,T≤105 题解 首先,膜拜一下PoPoQQQ大神及其题解 然后,有一个神奇的结论:ΣNi=1ΣMj=1d(ij)=ΣNi=1ΣMj=1[Ni][Mj][gcd(i,j)=1] 要证上式,只需证d(nm)=Σi|nΣj|m[gcd(i,j)=1],因为上式即为该式的前缀和形式. 分开考虑每个质数p对答案的贡献.设n=n′pk1,m=m′pk2,那p对d(nm)的贡献就是k1+k2+1,对等式右边的贡献是

洛谷P3327 [SDOI2015]约数个数和 【莫比乌斯反演】

题目 设d(x)为x的约数个数,给定N.M,求\(\sum_{i = 1}^{N} \sum_{j = 1}^{M} d(ij)\) 输入格式 输入文件包含多组测试数据.第一行,一个整数T,表示测试数据的组数.接下来的T行,每行两个整数N.M. 输出格式 T行,每行一个整数,表示你所求的答案. 输入样例 2 7 4 5 6 输出样例 110 121 提示 1<=N, M<=50000 1<=T<=50000 题解 好神的题[是我太弱吧] 首先上来就伤结论.. 题目所求 \(ans