[SDOI2015][bzoj 3994][Luogu P3327] 约数个数和 (莫比乌斯反演)
题目描述
设d(x)d(x)d(x)为xxx的约数个数,给定NNN、MMM,求 ∑i=1N∑j=1Md(ij)\sum^{N}_{i=1}\sum^{M}_{j=1} d(ij)i=1∑Nj=1∑Md(ij)
N,M,T<=50000N,M,T<=50000N,M,T<=50000
题目分析
首先很不显然的有这样一个结论:
d(ij)=∑x∣i∑y∣j[(x,y)==1]d(ij)=\sum_{x|i}\sum_{y|j}[(x,y)==1]d(ij)=x∣i∑y∣j∑[(x,y)==1]
证明如下
将一个数唯一质因数分解为p1k1p2k2p3k3...pnknp_1^{k_1}p_2^{k_2}p_3^{k_3}...p_n^{k_n}p1k1p2k2p3k3...pnkn,其约数个数为(k1+1)(k2+1)(k3+1)...(kn+1)(k_1+1)(k_2+1)(k_3+1)...(k_n+1)(k1+1)(k2+1)(k3+1)...(kn+1)
考虑一个质数ppp对d(ij)d(ij)d(ij)的影响,假设iii分解质因数后有kkk个ppp,jjj分解质因数后有qqq个ppp,则产生的贡献即为k+q+1k+q+1k+q+1,接下来是关键的一步(反正我想不到XD)
k+q+1=∑x=0k∑y=0q[(px,py)==1]k+q+1=\sum_{x=0}^k\sum_{y=0}^q[(p^x,p^y)==1]k+q+1=x=0∑ky=0∑q[(px,py)==1]
(此句可自行忽略:只有当xy=0xy=0xy=0时才会有值,这就相当于一个(k+1)∗(q+1)(k+1)∗(q+1)(k+1)∗(q+1)的矩形,只取了左下角的LLL字型的一块)
根据乘法原理,有
d(ij)=∑x1=0k1∑y1=0q1[(p1x1,p1y1)==1]∗∑x2=0k2∑y2=0q2[(p2x2,p2y2)==1]⋅⋅⋅∗∑xn=0kn∑yn=0qn[(pnxn,pnyn)==1]
d(ij)=\sum_{x_1=0}^{k_1}\sum_{y_1=0}^{q_1}[(p_1^{x_1},p_1^{y_1})==1]\newline
*\sum_{x_2=0}^{k_2}\sum_{y_2=0}^{q_2}[(p_2^{x_2},p_2^{y_2})==1]\newline
···\newline
*\sum_{x_n=0}^{k_n}\sum_{y_n=0}^{q_n}[(p_n^{x_n},p_n^{y_n})==1]
d(ij)=x1=0∑k1y1=0∑q1[(p1x1,p1y1)==1]∗x2=0∑k2y2=0∑q2[(p2x2,p2y2)==1]⋅⋅⋅∗xn=0∑knyn=0∑qn[(pnxn,pnyn)==1]
因为必须满足所有(pnxn,pnyn)==1(p_n^{x_n},p_n^{y_n})==1(pnxn,pnyn)==1才会对答案造成贡献,则可以变形为(∏i=1npnxn,∏i=1npnyn)==1(\prod_{i=1}^np_n^{x_n},\prod_{i=1}^np_n^{y_n})==1(i=1∏npnxn,i=1∏npnyn)==1
所以d(ij)=∑x∣i∑y∣j[(x,y)==1]d(ij)=\sum_{x|i}\sum_{y|j}[(x,y)==1]d(ij)=x∣i∑y∣j∑[(x,y)==1]
(以上证明摘自:传送门)
证毕
现在就有了Ans=∑i=1N∑j=1M∑x∣i∑y∣j[(x,y)==1]Ans=\sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{x|i}^{}\sum_{y|j}^{}[(x,y)==1]Ans=i=1∑Nj=1∑Mx∣i∑y∣j∑[(x,y)==1]
根据数论中切换枚举次序的套路以及莫比乌斯反演对布尔条件框的替换,我们得到
Ans=∑x=1N∑y=1M⌊Nx⌋⌊My⌋[(x,y)==1]=∑x=1N∑y=1M⌊Nx⌋⌊My⌋∑k∣(x,y)μ(k)=∑k=1min(N,M)μ(k)∑k∣x⌊Nx⌋∑k∣y⌊My⌋=∑k=1min(N,M)μ(k)∑x=1⌊Nk⌋⌊Nkx⌋∑y=1⌊Mk⌋⌊Mky⌋
Ans=\sum_{x=1}^{N}\sum_{y=1}^{M}⌊\frac{N}{x}⌋⌊\frac{M}{y}⌋[(x,y)==1]\newline
=\sum_{x=1}^{N}\sum_{y=1}^{M}⌊\frac{N}{x}⌋⌊\frac{M}{y}⌋\sum_{k|(x,y)}\mu(k)\newline
=\sum_{k=1}^{min(N,M)}\mu(k)\sum_{k|x}^{}⌊\frac{N}{x}⌋\sum_{k|y}^{}⌊\frac{M}{y}⌋\newline
=\sum_{k=1}^{min(N,M)}\mu(k)\sum_{x=1}^{⌊\frac{N}{k}⌋}⌊\frac{N}{kx}⌋\sum_{y=1}^{⌊\frac{M}{k}⌋}⌊\frac{M}{ky}⌋
Ans=x=1∑Ny=1∑M⌊xN⌋⌊yM⌋[(x,y)==1]=x=1∑Ny=1∑M⌊xN⌋⌊yM⌋k∣(x,y)∑μ(k)=k=1∑min(N,M)μ(k)k∣x∑⌊xN⌋k∣y∑⌊yM⌋=k=1∑min(N,M)μ(k)x=1∑⌊kN⌋⌊kxN⌋y=1∑⌊kM⌋⌊kyM⌋
于是这里使用分块优化,预处理μ\muμ的前缀和
最后考虑后面的两个Sigma怎么处理
可以观察发现它们都是∑i=1n⌊ni⌋\sum_{i=1}^{n}⌊\frac{n}{i}⌋∑i=1n⌊in⌋的形式,此处可以用分块优化Θ(nn)\Theta(n\sqrt{n})Θ(nn)预处理
其实还可以Θ(n)\Theta(n)Θ(n)预处理,可以发现∑i=1n⌊ni⌋=∑i=1n∑i∣dn1\sum_{i=1}^{n}⌊\frac{n}{i}⌋=\sum_{i=1}^{n}\sum_{i|d}^{n}1∑i=1n⌊in⌋=∑i=1n∑i∣dn1
显然是约数个数和d(n)d(n)d(n)的前缀和函数,于是线性筛出μ(n)\mu(n)μ(n)与d(n)d(n)d(n),求出前缀和即可
每次询问Θ(n)\Theta(\sqrt{n})Θ(n), 预处理Θ(n)\Theta(n)Θ(n),总时间复杂度为Θ(nn)\Theta(n\sqrt{n})Θ(nn)
TIPS
线性筛约数个数时存一下最小的质数p1p_1p1的次方+1+1+1,即存下(k1+1)(k_1+1)(k1+1)就可以方便的线性筛了
线性筛约数和同理,存一下最小的质数p1p_1p1所对应的首项为111,公比为p1p_1p1,项数为k1+1k_1+1k1+1的等比数列,即存下∑i=1k1p1i\sum_{i=1}^{k_1}p_1^i∑i=1k1p1i就可以愉快的线性筛了
AC code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100001;
namespace Mobius
{
#define LL long long
int Prime[MAXN], Cnt, mu[MAXN], d[MAXN], Minseq[MAXN];
bool IsnotPrime[MAXN];
LL sum_MU[MAXN], sum_D[MAXN];
void init()
{
mu[1] = d[1] = Minseq[1] = 1;
for(int i = 2; i < MAXN; ++i)
{
if(!IsnotPrime[i])
Prime[++Cnt] = i, mu[i] = -1, d[i] = Minseq[i] = 2;
for(int j = 1; j <= Cnt && i * Prime[j] < MAXN; ++j)
{
IsnotPrime[i * Prime[j]] = 1;
if(i % Prime[j] == 0)
{
Minseq[i * Prime[j]] = Minseq[i]+1;
mu[i * Prime[j]] = 0;
d[i * Prime[j]] = d[i] / Minseq[i] * Minseq[i * Prime[j]];
break;
}
Minseq[i * Prime[j]] = 2;
mu[i * Prime[j]] = -mu[i];
d[i * Prime[j]] = d[i]<<1;
}
}
for(int i = 1; i < MAXN; ++i)
sum_MU[i] = sum_MU[i-1] + mu[i],
sum_D[i] = sum_D[i-1] + d[i];
}
LL calc(int N, int M)
{
if(N > M) swap(N, M);
LL ret = 0;
for(int i = 1, j; i <= N; i=j+1)
{
j = min(N/(N/i), M/(M/i));
ret += (sum_MU[j]-sum_MU[i-1]) * sum_D[N/i] * sum_D[M/i];
}
return ret;
}
}
using namespace Mobius;
int main ()
{
init();
int T, n, m;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
printf("%lld\n", calc(n, m));
}
}
[SDOI2015][bzoj 3994][Luogu P3327] 约数个数和 (莫比乌斯反演)的更多相关文章
- P3327 [SDOI2015]约数个数和 莫比乌斯反演
P3327 [SDOI2015]约数个数和 莫比乌斯反演 链接 luogu 思路 第一个式子我也不会,luogu有个证明,自己感悟吧. \[d(ij)=\sum\limits_{x|i}\sum\li ...
- BZOJ 3994: [SDOI2015]约数个数和 [莫比乌斯反演 转化]
2015 题意:\(d(i)\)为i的约数个数,求\(\sum\limits_{i=1}^n \sum\limits_{j=1}^m d(ij)\) \(ij\)都爆int了.... 一开始想容斥一下 ...
- luogu P3327 [SDOI2015]约数个数和 莫比乌斯反演
题面 我的做法基于以下两个公式: \[[n=1]=\sum_{d|n}\mu(d)\] \[\sigma_0(i*j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\] 其中\(\ ...
- BZOJ 3994: [SDOI2015]约数个数和3994: [SDOI2015]约数个数和 莫比乌斯反演
https://www.lydsy.com/JudgeOnline/problem.php?id=3994 https://blog.csdn.net/qq_36808030/article/deta ...
- [BZOI 3994] [SDOI2015]约数个数和(莫比乌斯反演+数论分块)
[BZOI 3994] [SDOI2015]约数个数和 题面 设d(x)为x的约数个数,给定N.M,求\(\sum _{i=1}^n \sum_{i=1}^m d(i \times j)\) T组询问 ...
- 洛谷P3327 [SDOI2015]约数个数和(莫比乌斯反演)
题目描述 设d(x)为x的约数个数,给定N.M,求 \sum^N_{i=1}\sum^M_{j=1}d(ij)∑i=1N∑j=1Md(ij) 输入输出格式 输入格式: 输入文件包含多组测试数据.第 ...
- 【BZOJ3994】[SDOI2015]约数个数和 莫比乌斯反演
[BZOJ3994][SDOI2015]约数个数和 Description 设d(x)为x的约数个数,给定N.M,求 Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组 ...
- [SDOI2015][bzoj3994] 约数个数和 [莫比乌斯反演]
题面: 传送门 思路: 首先,我们需要证明一个结论:d(i*j)等于sigma(gcd(x,y)==1),其中x为i的约数,y为j的约数 对于nm的每一个质因子pi分别考虑,设n = pi^ai + ...
- BZOJ3994: [SDOI2015]约数个数和(莫比乌斯反演)
Description 设d(x)为x的约数个数,给定N.M,求 Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Out ...
随机推荐
- pytorch1.0实现RNN for Regression
import torch from torch import nn import numpy as np import matplotlib.pyplot as plt # 超参数 # Hyper P ...
- quartz定时任务存储
今天不聊quartz的概念,像任务bean,触发器,调度器这些随随便便都可以百度到,其中任务bean要实现job接口.对于这些创建生成的定时任务,它可以保存在内存中,重启失效,也可以保存在数据库里重启 ...
- Aes 加密解密 java加密解密
使用AES加密解密代码详解 首先,如果是使用nodejs + vue 写的前端, 那么你需要npm 加载一个js文件 npm i crypto-js --save --save-exact npm i ...
- Python32之类和对象2(self参数及魔法方法)
一.类方法中的self参数含义 在Python中类的方法都要有self参数,其实质为对类的实例化对象的绑定从而使得在类的实例化对象调用方法时能够确认出是对哪个对象进行操作. 带self的的参数是人家实 ...
- 搭建hexo静态博客
使用hexo搭建博客,并将博客部署到github 需要的工具 Node.js Git 一个Github账号 正式开始 在任意目录下新建一个文件夹,如blog,在该文件夹下右键打开git bash he ...
- [UOJ#404][CTSC2018]组合数问题(79分,提交答案题,模拟退火+匈牙利+DP)
1.4.5.6.10都是op=1的点,除4外直接通过模拟退火调参可以全部通过. #include<cmath> #include<ctime> #include<cstd ...
- 网页调试js时,如何知道某个事件对应哪段js代码?
有时候我们需要知道某个事件对应的js代码,比如点击一个div元素时,出现下拉框,我想知道这个功能对应的js代码,那就可以按下图操作: 勾选click事件,重新运行,那么就会在每个click事件那里设置 ...
- idea for mac 快捷键整理
⌘O 查找类文件 ⌘⌥O 前往指定的变量 / 方法 ⌘⇧O 查找所有类型文件.打开文件.打开目录,打开目录需要在输入的内容前面或后面加一个反斜杠/ ⌘⌥← / ⌘⌥→ 退回 / 前进到上一个操作的地方 ...
- windows + Eclipse
https://www.eclipse.org/downloads/index-packages.php 下载好后是一个压缩文件,解压并放到相要存放软件的目录,双击打开解压后的目录下eclipse.e ...
- Java Web-JQuery学习
Java Web-JQuery学习 JQuery概念 是一个JS框架,可以用来简化JS的开发,设计宗旨是"write less,do more",即写更少的代码,做更多的事情.它封 ...