luogu P3327 [SDOI2015]约数个数和 莫比乌斯反演

题面

我的做法基于以下两个公式:

\[[n=1]=\sum_{d|n}\mu(d)\]
\[\sigma_0(i*j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\]
其中\(\sigma_0(n)\)表示\(n\)的约数个数

第一个公式是莫比乌斯函数的基本性质,至于第二个公式的证明,可以考虑\(i*j\)中每一个质因子对 \(\sigma_0(i*j)\) 的贡献,对于一个质因子 \(p\) ,若它在 \(i\) 中的次数为 \(k_1\) ,它在 \(j\) 中的次数为 \(k_2\) ,则在 \(\sigma_0(i*j)\) 中\(p\)的贡献为\((k_1+k_2+1)\)(约数个数计算公式),而在\(gcd(x,y)=1\)的情况下,要么\(x\)中\(p\)的次数为0,要么\(y\)中\(p\)的次数为0,一共有\((k_1+k_2+1)\)种方案,与\(i*j\)中的贡献相同,所以等式左右两边相等。

然后就可以愉快的推式子啦!

\[ \sum_{i=1}^{n} \sum_{j=1}^{m}\sigma_0(i*j)\]

\[ \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 \sum_{i=1}^{\lfloor \frac{n}{x} \rfloor } \sum_{j=1}^{\lfloor \frac{m}{y}\rfloor} [gcd(x,y)=1]\]

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

\[\sum_{k=1}^{n}\sum_{x=1}^{\lfloor \frac{n}{k}\rfloor}\sum_{y=1}^{\lfloor \frac{m}{k} \rfloor} \lfloor \frac{n}{kx}\rfloor \lfloor \frac{m}{ky} \rfloor\mu(k)\]

\[\sum_{k=1}^{n}\mu(k)(\sum_{x=1}^{\lfloor \frac{n}{k}\rfloor}\lfloor\frac{n}{kx}\rfloor)(\sum_{y=1}^{\lfloor\frac{m}{k}\rfloor}\lfloor\frac{m}{ky}\rfloor)\]

然后我们设\(S(n)=\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor\),显然\(S(n)\)是可以\(O(\sqrt{n})\)计算的

则上式可化为:

\[\sum_{k=1}^{n}\mu(k)S(\lfloor\frac{n}{k}\rfloor)S({\lfloor\frac{m}{k}\rfloor})\]

先预处理\(S(1)-S(maxn)\),然后就可以\(O(\sqrt{n})\)回答每组询问啦!

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 50007
#define ll long long
const int lim=50000;
ll s[N];
int ui[N],pr[N],cnt;
bool zhi[N];
void Init()
{
    int i,j;
    ui[1]=1;
    for(i=2;i<=lim;i++)
    {
        if(!zhi[i])
        {
            pr[++cnt]=i;
            ui[i]=-1;
        }
        for(j=1;j<=cnt&&i*pr[j]<=lim;j++)
        {
            int p=pr[j],x=i*p;
            zhi[x]=true;
            if(i%p==0)
            {
                ui[x]=0;
                break;
            }
            ui[x]=-ui[i];
        }
    }
    for(i=1;i<=lim;i++)
        ui[i]+=ui[i-1];
    for(i=1;i<=lim;i++)
    {
        int l,r;
        for(l=1;l<=i;l=r+1)
        {
            r=i/(i/l);
            s[i]+=1ll*(r-l+1)*(i/l);
        }
    }
}
int main()
{
    int n,m,t;
    Init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int l1=1,r1,l2=1,r2,cur=1;
        ll ans=0;
        while(l1<=n&&l2<=m)
        {
            int l,r;
            r1=n/(n/l1),r2=m/(m/l2);
            l=cur;
            if(r1<r2)r=r1,cur=l1=r1+1;
            else r=r2,cur=l2=r2+1;
            ans+=1ll*(ui[r]-ui[l-1])*s[n/l]*s[m/l];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lishuyu2003/p/11257123.html

时间: 2024-10-10 16:22:37

luogu P3327 [SDOI2015]约数个数和 莫比乌斯反演的相关文章

[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\

【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

BZOJ 3994 Sdoi2015 约数个数和 莫比乌斯反演

题目大意:求∑ni=1∑mj=1d(ij) 首先我们有一个很神的结论: ∑ni=1∑mj=1d(ij)=∑ni=1∑mj=1?ni??mj?[gcd(i,j)==1] 这个结论是怎么来的呢?我们可以先证明这个: d(nm)=∑i|n∑j|m1?1[gcd(i,j)==1] 显然这个式子的前缀和就是上面的式子 现在我们来证明这个式子是对的 我们分开讨论每一个质数p对答案的贡献 不妨设n=n′?pk1,m=m′?pk2 那么左式中p的贡献显然是k1+k2+1 右式中只考虑p的话,满足要求的数对(i,

洛谷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

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

题面: 传送门 思路: 首先,我们需要证明一个结论:d(i*j)等于sigma(gcd(x,y)==1),其中x为i的约数,y为j的约数 对于nm的每一个质因子pi分别考虑,设n = pi^ai + n',m = pi^bi + m' 那么显然质因子pi对d(nm)的贡献为(ai+bi+1) 同理,考虑右边的式子,我们发现质数pi对右侧做的贡献仍然是(ai+bi+1),即如下的(x,y) (pi^ai,1) (pi^(ai-1),1) ..... (1,1) .....(1,pi^(bi-1))

洛谷P3327 [SDOI2015]约数个数和

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

P3327 [SDOI2015]约数个数和

传送门 首先证明 $d(ij)=\sum_{k|i}\sum_{l|j}[gcd(k,l)==1]$ 把 $i,j$ 考虑成唯一分解后的形式:$P_{i1}^{k1}P_{i2}^{k2}...P_{in}^{kn}$ 对于 $i,j$ 中某个相同的质因子 $P_{x}$ ,$i=...P_{x}^{ki}...$,$j=...P_{x}^{kj}...$ 如果枚举到 $j$ 中因数 $l$ 时,$l$ 有因数 $P_{x}^{t}$,不妨看成 $P_{x}^{ki+t}$, 如果这样看,那么会

[BZOJ 3994]约数个数和 莫比乌斯反演

自己是在是弱,看了半天才看懂题解 写公式实在是麻烦,搬家一份: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #define N 101000 #define pos(i,a,b) for(int i=(a);i<=(b);i++) using namespace std; #define LL long long int t,n,m; int notpr

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