题面

求\(\sum_{i=1}^n\sum_{j=1}^md(ij)\)

\(\leq 50000\)组数据,\(1\leq n,m\leq 50000\)。

题目分析

首先,你需要知道一个结论:

\[d(ij)=\sum\limits_{x|i}\sum\limits_{y|j}[gcd(x,y)==1]
\]

你可以认为\(x,y\)表示你选择的因数为\(\frac i x \cdot y\),即:\(x\)表示\(i\)中不要的部分,\(y\)表示\(j\)中要的部分。

如果\(gcd(x,y)==p_i\),那么\(\frac i x\)表示在约数中拿掉\(p_i\),\(y\)表示在约数中加入\(p_i\),这样一拿一加,自然会在答案中重复。


那么,现在我们的问题转化为求

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

这样还是无法计算,所以我们把枚举因数提前

\[\sum\limits_{x=1}^n\sum\limits_{y=1}^n\lfloor\frac n x\rfloor\lfloor\frac m y\rfloor[gcd(x,y)==1]
\]

现在看起来就可以反演了,设\(f(x)\)表示\(gcd(i,j)==x\)时的答案,\(g(x)\)表示\(gcd(i,j)==kx,k\in Z\)时的答案,则:

\[\begin{split}
f(x)&=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\lfloor\frac n i\rfloor\lfloor\frac m j\rfloor[gcd(i,j)==x]\\
g(x)&=\sum\limits_{x|d}^nf(d)\\
&=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\lfloor\frac n i\rfloor\lfloor\frac m j\rfloor[x|gcd(i,j)]\\
&=\sum\limits_{i=1}^{\lfloor\frac n x\rfloor}\sum\limits_{j=1}^{\lfloor\frac m x\rfloor}\lfloor\frac n {ix}\rfloor\lfloor\frac m {jx}\rfloor\\
&=\sum\limits_{i=1}^{\lfloor\frac n x\rfloor}\lfloor\frac n {ix}\rfloor\sum\limits_{j=1}^{\lfloor\frac m x\rfloor}\lfloor\frac m {jx}\rfloor
\end{split}
\]


比较巧的一点是:\(\sum\limits_{i=1}^n\lfloor\frac n i\rfloor\)可以表示\(1 \sim n\)的约数个数的前缀和。

约数个数可以在线性筛中预处理,原理如下:

对于\(x=p_1^{a_1}p_2^{a_2}p_3^{a_3}...p_n^{a_n}\),\(x\)的约数个数为\((a_1+1)\cdot(a_2+1)\cdot(a_3+1)\cdot...\cdot(a_n+1)\)

由于在线性筛中,每个数只会被它最小的质因子更新,所以:

如果\(i\%prime[j]==0\),说明\(i\)中含有\(prime[j]\),此时\(x\)中\(prime[j]\)的个数为\(i\)中\(prime[j]\)的个数\(+1\),\(x\)的约数个数=\(i\)的约数个数/(\(i\)中\(prime[j]\)的个数)*(\(i\)中\(prime[j]\)的个数\(+1\));

如果\(i\%prime[j]!=0\),说明\(prime[j]\)在\(x\)中只有\(1\)个,\(x\)的约数个数=\(i\)的约数个数*\(2\)。


这样一来\(g(x)\)可以进行预处理,然后\(O(1)\)计算。

反演得\(f(x)=\sum\limits_{x|d}^n\mu(\frac dx)g(d)\),为了针对多组数据,整除分块即可。

代码实现

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#define MAXN 0x7fffffff
typedef long long LL;
const int N=50005;
using namespace std;
inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
int mu[N],prime[N];
bool vis[N]; int ys[N],lw[N],g[N];
int main(){
mu[1]=g[1]=1;
for(int i=2;i<=50000;i++){
if(!vis[i])prime[++prime[0]]=i,mu[i]=-1,ys[i]=2,lw[i]=1;
for(int j=1;j<=prime[0]&&i*prime[j]<=50000;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0){
ys[i*prime[j]]=ys[i]/(lw[i]+1)*(lw[i]+2);
lw[i*prime[j]]=lw[i]+1;
break;
}
mu[i*prime[j]]=-mu[i];
ys[i*prime[j]]=ys[i]*2,lw[i*prime[j]]=1;
}
mu[i]+=mu[i-1],g[i]=g[i-1]+ys[i];
} int T=Getint();
while(T--){
int n=Getint(),m=Getint();
if(n>m)swap(n,m);
LL ans=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=1ll*(mu[r]-mu[l-1])*g[n/l]*g[m/l];
}
cout<<ans<<'\n';
}
return 0;
}

【SDOI2015】约数个数和的更多相关文章

  1. BZOJ_3994_[SDOI2015]约数个数和_莫比乌斯反演

    BZOJ_3994_[SDOI2015]约数个数和_莫比乌斯反演 Description  设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表 ...

  2. P3327/bzoj3994 [SDOI2015]约数个数和(莫比乌斯反演)

    P3327 [SDOI2015]约数个数和 神犇题解(转) 无话可补 #include<iostream> #include<cstdio> #include<cstri ...

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

    3994: [SDOI2015]约数个数和 Description  设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接 ...

  4. 洛谷 [SDOI2015]约数个数和 解题报告

    [SDOI2015]约数个数和 题目描述 设\(d(x)\)为\(x\)的约数个数,给定\(N,M\),求$ \sum\limits^N_{i=1}\sum\limits^M_{j=1}d(ij)$ ...

  5. BZOJ 3994: [SDOI2015]约数个数和

    3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 898  Solved: 619[Submit][Statu ...

  6. 【BZOJ3994】[SDOI2015]约数个数和 莫比乌斯反演

    [BZOJ3994][SDOI2015]约数个数和 Description  设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组 ...

  7. 洛谷P3327 - [SDOI2015]约数个数和

    Portal Description 共\(T(T\leq5\times10^4)\)组数据.给出\(n,m(n,m\leq5\times10^4)\),求\[\sum_{i=1}^n\sum_{j= ...

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

    P3327 [SDOI2015]约数个数和 莫比乌斯反演 链接 luogu 思路 第一个式子我也不会,luogu有个证明,自己感悟吧. \[d(ij)=\sum\limits_{x|i}\sum\li ...

  9. [BZOI 3994] [SDOI2015]约数个数和(莫比乌斯反演+数论分块)

    [BZOI 3994] [SDOI2015]约数个数和 题面 设d(x)为x的约数个数,给定N.M,求\(\sum _{i=1}^n \sum_{i=1}^m d(i \times j)\) T组询问 ...

  10. 【BZOJ】3994: [SDOI2015]约数个数和

    题意: \(T(1 \le T \le 50000)\)次询问,每次给出\(n, m(1 \le n, m \le 50000)\),求\(\sum_{i=1}^{n} \sum_{j=1}^{m} ...

随机推荐

  1. python中oop

    转自  http://www.cnblogs.com/BeginMan/p/3510786.html 本文旨在Python复习和总结: 1.如何创建类和实例? # 创建类 class ClassNam ...

  2. USACO2008 Roads Around The Farm /// queue oj23321

    题目大意: N (1 ≤ N ≤ 1,000,000,000)牛群在遇到岔路时,若能分为恰好相差 K (1 ≤ K ≤ 1000)的两路,则持续分裂(假设会一直遇到岔路),否则停止开始吃草. Inpu ...

  3. 收藏的链接-English

    What is the adverb for deposit? https://www.wordhippo.com/what-is/the-adverb-for/deposit.html

  4. ubontu 16 下的 pylon5 安装

    想用wine,然后走了很多弯路.后来发现正确的安装和配置pylon即可.注意32位和64位不可以混淆. If you choose to install in a different director ...

  5. mysql连接数问题备份

    一. max_connections 这是是查询数据库当前设置的最大连接数 mysql> show variables like '%max_connections%';+----------- ...

  6. Django项目基础配置和基本使用

    博文配置内容包括: django项目的创建 django项目下应用的创建及配置 数据库的配置 templates模板的配置 命令行创建项目: 在需要的目录下创建Django项目输入命令:django- ...

  7. layer.confirm等事件X关闭与取消监听

    关于layer.confirm的所有操作 layer.confirm('content',{ btn:['确定','取消'], cancel:function(index, layero){ cons ...

  8. Eclipse中如何使用Hibernate

    首先创建一个java web项目,其目录如下: (1)创建文件夹hibernate4(用于存放下载的hibernate工具包lib/required文件夹下所有的jar包),jar包目录如下: (2) ...

  9. VC 复制移动删除重命名文件文件

    说明: 1.以下封装了4个函数_CopyFile,_DeleteFile,_MoveFile,_ReNameFile 2.每个函数都先拷贝了原来的路径,保证了路径是以2个\0\0结尾.(如果不以2个\ ...

  10. golang中time包一个简单的时间格式输出

    一.代码 package main import ( "fmt" "time" ) func main() { //"2006-01-02 15:04 ...