「BZOJ 3529」「SDOI 2014」数表「莫比乌斯反演」
题意
有一张 \(n\times m\) 的数表,其第\(i\)行第\(j\)列的数值为能同时整除\(i\)和\(j\)的所有自然数之和。
\(T\)组数据,询问对于给定的 \(n,m,a\) , 计算数表中\(\leq a\) 的数之和。
\(T \leq 2\times 10^4,1 \leq n,m\leq 10^5\).
题解
令\(\sigma(x)\)表示\(x\)的约数和,容易写出答案的式子:
\]
然后使用常见套路变换式子:(下面默认\(n\leq m\))
\]
\]
\]
\]
我们记前面那部分\(f(d)=\sigma(d)[\sigma(d)\leq a]\):
\]
枚举乘积\(k=dd'\):
\]
可以发现后面变成了狄利克雷卷积的形式!
记$$g(k)=\sum_{d|k} f(d)\mu(\frac{k}{d})$$,即\(g=f*\mu\):
\]
可以看出我们对于每个\(n,m\),可以数论分块
但是\(g(k)\)会随着\(a\)的变化而变化,不能每次计算一遍\(g\)
但是注意到,\(g\)变化是因为\(f\),\(f\)只有\(10^5\)种取值。
于是我们可以把询问离线后按\(a\)从小到大排序,每次加入一些满足\(\sigma(d)\leq a\)的\(d\)
然后考虑加入一个\(d\)有什么影响:使得所有\(d|k\)的\(g(k)\)加上\(f(d)\mu(\frac{k}{d})\)
就可以每次枚举\(d\)的倍数\(k\),然后更新\(g(k)\),最多更新\([1,n]\)这些数,根据调和级数可得枚举的总复杂度为\(O(n \log n)\)
别忘了数论分块是需要前缀和的,
所以现在我们需要一种支持快速单点加、求前缀和的数据结构,树状数组就很合适
然后就做完了,复杂度\(O(n \log^2 n+T\sqrt n \log n)\)
一个小细节:\(\sigma\)函数怎么线性筛?
考虑质因数分解后\(\sigma (x)=(1+p_1+p_1^2+..+p_1^{c_1})..(1+p_k+p_k^2+..+p_k^{c_k})\)
因此线性筛的时候记录一个\(tmp(x)\)表示\(1+p+p^2..+p^c\),其中\(p\)为\(x\)的最小质因子,\(c\)的\(p\)的指数;然后就可以做了
一个减小常数的小技巧:分块的时候记录一个变量,减少重复的询问,详见代码
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int R = 1e5;
const int N = 1e5 + 10;
const int M = 2e4 + 10;
const ll mo = 1ll << 31;
struct qs {
int n, m, a, id;
bool operator < (const qs &b) const {
return a < b.a;
}
} q[M];
int t, tot, p[N], mu[N], sig[N], tmp[N], ans[M];
bool tag[N];
struct num {
int x;
bool operator < (const num &b) const {
return sig[x] < sig[b.x];
}
} a[N];
void sieve(int n) {
sig[1] = mu[1] = 1;
for(int i = 2; i <= n; i ++) {
if(!tag[i]) {
p[tot ++] = i; mu[i] = -1;
sig[i] = tmp[i] = i + 1;
}
for(int j = 0; j < tot; j ++) {
if(p[j] * i > n) break ;
tag[i * p[j]] = 1;
if(i % p[j] == 0) {
mu[i * p[j]] = 0;
tmp[i * p[j]] = tmp[i] * p[j] + 1;
sig[i * p[j]] = sig[i] / tmp[i] * tmp[i * p[j]];
break ;
}
mu[i * p[j]] = - mu[i];
tmp[i * p[j]] = 1 + p[j];
sig[i * p[j]] = sig[i] * (1 + p[j]);
}
}
for(int i = 1; i <= n; i ++) a[i].x = i;
sort(a + 1, a + n + 1);
}
int bit[N];
void add(int x, int y) {
for(; x <= R; x += x & (-x))
bit[x] = ((ll) bit[x] + y) % mo;
}
int qry(int x) {
int ans = 0;
for(; x >= 1; x &= x - 1)
ans = ((ll) ans + bit[x]) % mo;
return ans;
}
void ins(int x) {
for(int k = 1; x * k <= R; k ++)
add(x * k, (ll) mu[k] * sig[x] % mo);
}
int query(int n, int m) {
int ans = 0, la = 0, nw;
for(int i = 1, j; i <= n; i = j + 1, la = nw) {
j = min(n / (n / i), m / (m / i)); nw = qry(j);
ans = (ans + ((ll) nw - la) % mo * (n / i) % mo * (m / i) % mo) % mo;
}
return ((ll)ans + mo) % mo;
}
int main() {
sieve(R); scanf("%d", &t);
for(int i = 1; i <= t; i ++) {
scanf("%d%d%d", &q[i].n, &q[i].m, &q[i].a);
if(q[i].n > q[i].m) swap(q[i].n, q[i].m);
q[i].id = i;
}
sort(q + 1, q + t + 1);
int j = 1;
for(int i = 1; i <= t; i ++) {
for(; j <= R && sig[a[j].x] <= q[i].a; j ++) ins(a[j].x);
ans[q[i].id] = query(q[i].n, q[i].m);
}
for(int i = 1; i <= t; i ++)
printf("%d\n", ans[i]);
return 0;
}
「BZOJ 3529」「SDOI 2014」数表「莫比乌斯反演」的更多相关文章
- 【BZOJ 3529】【SDOI 2014】数表
看Yveh的题解,这道题卡了好长时间,一直不明白为什么要······算了当时太naive我现在都不好意思说了 #include<cstdio> #include<cstring> ...
- 「BZOJ 3994」「SDOI 2015」约数个数和「莫比乌斯反演」
题意 设\(d(x)\)为\(x\)的约数个数,求\(\sum_{i=1}^{n}\sum_{j=1}^{m}d(ij)\). 题解 首先证个公式: \[d(ij) = \sum_{x|i}\sum_ ...
- ☆ [POI2007] ZAP-Queries 「莫比乌斯反演」
题目类型:莫比乌斯反演 传送门:>Here< 题意:求有多少对正整数对\((a,b)\),满足\(0<a<A\),\(0<b<B\),\(gcd(a,b)=d\) ...
- 「CF235E」Number Challenge「莫比乌斯反演」
一个结论:(从二维扩展来的,三维也是对的,证明可以考虑质因数分解) \[ d(ijk)=\sum_{i'|i}\sum_{j'|j}\sum_{k'|k}[\gcd(i',j')=1][\gcd(i' ...
- 【BZOJ 3531】【SDOI 2014】旅行
因为有$10^5$个宗教,需要开$10^5$个线段树. 平时开的线段树是“满”二叉树,但在这个题中代表一个宗教的线段树管辖的区间有很多点都不属于这个宗教,也就不用“把枝叶伸到这个点上”,所以这样用类似 ...
- 【BZOJ 3530】【SDOI 2014】数数
http://www.lydsy.com/JudgeOnline/problem.php?id=3530 上午gty的测试题,爆0了qwq 类似文本生成器那道题,把AC自动机的转移建出来,准确地说建出 ...
- bzoj 3529 [Sdoi2014]数表(莫比乌斯反演+BIT)
Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a ...
- 【SDOI 2014】数表
题意 https://loj.ac/problem/2193 题解 显然就是求 $\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m} \sigma_1(\gcd{ ...
- BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)
2005: [Noi2010]能量采集 Time Limit: 10 Sec Memory Limit: 552 MBSubmit: 4493 Solved: 2695[Submit][Statu ...
随机推荐
- Day2-VIM(五):复制
粘帖 p 粘帖 复制的形式可以很多,但是粘帖的形式却没多少 无非就是加数字达到多次粘帖什么的 其实准确的说,p应该是放置的意思 不过我也搞不清是paste还是put的缩写 单词和字符复制 ynl 向右 ...
- Windows10:怎么安装whl文件
whl格式本质上是一个压缩包,里面包含了py文件,以及经过编译的pyd文件.使得可以在不具备编译环境的情况下,选择合适自己的python环境进行安装.安装方法很简单,进入命令行输入pip instal ...
- web.xml中classpath表示什么样的路径
首先 classpath是指 WEB-INF文件夹下的classes目录 解释classes含义: 1.存放各种资源配置文件 eg.init.properties log4j.properties ...
- 2015.3.7 Dll CString不能作为传入参数而要用char*
extern "C" __declspec(dllexport) void CalcArc_2(Point2D& pm, double am, double an, CSt ...
- QT5提示can not find -lGL的解决方法
这是由于 Qt5.0 默认将OpenGL加入了工程,但是在机器上没有安装OpenGL,所以jonas只需要在机器上安装OpenGL即可 . 安装建立基本编译环境 首先不可或缺的,就是编译器与基本的 ...
- leetcode559
class Solution { public: int maxDepth(Node* root) { ; if (root != NULL) { queue<Node> Q; Q.pus ...
- Git实用技巧
1.关于版本控制系统 (1)本地版本控制系统 (2)集中化的版本控制系统 (3)分布式版本控制系统 2.Git的三种状态 对于任何一个文件,在 Git 内都只有三种状态: 已提交(committed) ...
- OpenGL 着色器 03
着色器(shader)是运行在GPU上小程序. 也是一种非常独立的程序,它们之间不能相互通信:它们之间唯一的沟通只有通过输入和输出. 着色器的开头总是要声明版本,接着是输入和输出变量,uniform和 ...
- c#.net常用字符串函数 字符串常用方法 string
RegionsStr = RegionsStr.Remove(RegionsStr.LastIndexOf(","), 1); //去掉最后一个逗号 string html = ...
- 7-EasyNetQ之Request & Response
EasyNetQ也支持Request/Response这种方式的消息模式.这种方式很容易在client/Server应用中执行,客户端发送一个请求到服务器,服务器然后处理请求后返回一个响应.和传统的R ...