[SDOI2015]约数个数和 莫比乌斯反演
题解:
为什么SDOI这么喜欢莫比乌斯反演,,,
首先有一个结论$$d(ij) = \sum_{x|i}\sum_{y|j}[gcd(x, y) == 1]$$
为什么呢?
首先,可以看做从两个数中分别取一些不重叠的质数的$k_{i}$次方,组成新数的方案数。
那如果有需要重叠的部分怎么办?
可以看做全都在第一个or第二个数中取。
但是一个数的次数不够怎么办呢?
相当于以1为媒介,可以简介统计到这些情况
比如$2^{3} \cdot 2^{2} = 2^{5}$可以看成$1, 2^{3}$ + $1, 2^{2}$,这样就可以做到分别枚举了指数从1到5的情况了;
$$ans = \sum_{i = 1}^{n}\sum_{j = 1}^{m}\sum_{x | i}\sum_{y | j}[gcd(x, y) == 1]$$
$$ans = \sum_{x = 1}^{n}\sum_{y = 1}^{m} \lfloor{\frac{n}{x}}\rfloor \lfloor{\frac{m}{y}}\rfloor [gcd(x, y) == 1]$$<---改成枚举x和y,然后统计有多少对i,j中分别含有因数x,y
设$$f(d) = \sum_{x = 1}^{n}\sum_{y = 1}^{m} \lfloor{\frac{n}{x}}\rfloor \lfloor{\frac{m}{y}}\rfloor [gcd(x, y) == d]$$, $$g(x) = \sum_{x | d}^{min(n, m)}{f(d)}$$
那么$ans = f(1)$
反演一下得到:$$f(n) = \sum_{n | d}\mu(\frac{d}{n}) \cdot g(d)$$
接下来就是怎么求$g(d)$了。
$$g(d) = \sum_{x = 1}^{n}\sum_{y = 1}^{m} \lfloor{\frac{n}{x}}\rfloor \lfloor{\frac{m}{y}}\rfloor [d | gcd(x, y)]$$
$d | gcd(x, y)$ ---> $d | x + d | y$ ,因为$x | n + y | m$ ---> $d | n + d | m$
所以枚举$d_{i}$就符合条件了,$\lfloor{\frac{n}{dx}}\rfloor$ ---> $dx$倍数的个数,即有多少i,j的搭配是可以满足$[d|gcd(x, y)]$的
$$g(d) = \sum_{x = 1}^{ \lfloor{\frac{n}{d}}\rfloor }\sum_{y = 1}^{ \lfloor{\frac{m}{d}}\rfloor } \lfloor{\frac{n}{dx}}\rfloor \lfloor{\frac{m}{dy}}\rfloor$$
于是现在就是要求$f(1)$
$$f(1) = \sum_{d = 1}^{min(n, m)}{\mu(\frac{d}{1})g(d)}$$
$$= \sum_{d = 1}^{min(n, m)}{\mu(d)g(d)}$$
$$= \sum_{d = 1}^{min(n, m)}{\mu(d) \cdot \sum_{x = 1}^{ \lfloor{\frac{n}{d}}\rfloor }\sum_{y = 1}^{ \lfloor{\frac{m}{d}}\rfloor } \lfloor{\frac{n}{dx}}\rfloor \lfloor{\frac{m}{dy}}\rfloor}$$
这个式子可以整数分块。
设$N = \frac{n}{d}$, $M = \frac{m}{d}$,那么
$$= \sum_{d = 1}^{min(n, m)}{\mu(d) \cdot \sum_{x = 1}^{ N }\sum_{y = 1}^{ M } \lfloor{\frac{N}{x}}\rfloor \lfloor{\frac{M}{y}}\rfloor}$$
$$= \sum_{d = 1}^{min(n, m)}{\mu(d) \cdot \sum_{x = 1}^{ N}{\lfloor{\frac{N}{x}}\rfloor} \sum_{y = 1}^{M} {\lfloor{\frac{M}{y}}\rfloor}}$$
而$N = \lfloor{\frac{n}{d}}\rfloor$, $M = \lfloor{\frac{m}{d}}\rfloor$有很多相同的区间段,所以可以整数分块求。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 50100
#define ac 50000
#define LL long long
int n, m, tot, t;
LL ans;
int prime[AC];
LL mu[AC], s[AC];
bool z[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();//error!!!又一次打错了读入优化。。。是||啊
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} void pre()
{
int x;
mu[] = ;
for(R i = ; i <= ac; i++)
{
if(!z[i]) prime[++tot] = i, mu[i] = -;
for(R j = ; j <= tot; j++)
{
x = prime[j];
if(x * i > ac) break;
z[x * i] = true;
if(!(i % x)) break;
mu[i * x] = -mu[i];
}
}
for(R i = ; i <= ac; i++) mu[i] += mu[i-];
int pos;
for(R i = ; i <= ac; i++)
{
for(R j = ; j <= i; j = pos + )
{
pos = i / (i / j);
s[i] += (LL)(i / j) * (LL)(pos - j + );
}
}
// for(R i = 1; i <= 30; i++) printf("%lld\n", s[i]);
} void work()
{
t = read();
while(t--)
{
n = read(), m = read(), ans = ;
//scanf("%d%d", &n, &m);ans = 0;
int pos, b = min(n, m);
for(R i = ; i <= b; i = pos + )
{
pos = min(n / (n / i), m / (m / i));
ans += (mu[pos] - mu[i - ]) * s[n / i] * s[m / i];
}
printf("%lld\n", ans);
}
} int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}
[SDOI2015]约数个数和 莫比乌斯反演的更多相关文章
- P3327 [SDOI2015]约数个数和 莫比乌斯反演
P3327 [SDOI2015]约数个数和 莫比乌斯反演 链接 luogu 思路 第一个式子我也不会,luogu有个证明,自己感悟吧. \[d(ij)=\sum\limits_{x|i}\sum\li ...
- 【BZOJ3994】[SDOI2015]约数个数和 莫比乌斯反演
[BZOJ3994][SDOI2015]约数个数和 Description 设d(x)为x的约数个数,给定N.M,求 Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组 ...
- [BZOI 3994] [SDOI2015]约数个数和(莫比乌斯反演+数论分块)
[BZOI 3994] [SDOI2015]约数个数和 题面 设d(x)为x的约数个数,给定N.M,求\(\sum _{i=1}^n \sum_{i=1}^m d(i \times j)\) T组询问 ...
- 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]约数个数和 [莫比乌斯反演 转化]
2015 题意:\(d(i)\)为i的约数个数,求\(\sum\limits_{i=1}^n \sum\limits_{j=1}^m d(ij)\) \(ij\)都爆int了.... 一开始想容斥一下 ...
- BZOJ 3994: [SDOI2015]约数个数和3994: [SDOI2015]约数个数和 莫比乌斯反演
https://www.lydsy.com/JudgeOnline/problem.php?id=3994 https://blog.csdn.net/qq_36808030/article/deta ...
- 洛谷P3327 [SDOI2015]约数个数和(莫比乌斯反演)
题目描述 设d(x)为x的约数个数,给定N.M,求 \sum^N_{i=1}\sum^M_{j=1}d(ij)∑i=1N∑j=1Md(ij) 输入输出格式 输入格式: 输入文件包含多组测试数据.第 ...
- BZOJ3994: [SDOI2015]约数个数和(莫比乌斯反演)
Description 设d(x)为x的约数个数,给定N.M,求 Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Out ...
- BZOJ.3994.[SDOI2015]约数个数和(莫比乌斯反演)
题目链接 \(Description\) 求\[\sum_{i=1}^n\sum_{j=1}^md(ij)\] \(Solution\) 有结论:\[d(nm)=\sum_{i|d}\sum_{j|d ...
随机推荐
- 11、Java并发编程:并发容器之CopyOnWriteArrayList
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- 拼接index
import MySQLdb import sys db = MySQLdb.connect(host="127.0.0.1", # your host, usually loca ...
- uvaoj1339 - Ancient Cipher(思维题,排序,字符串加密)
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- Selenium(Python)生成Html测试报告
由于Python3已经不支持HTMLTestRunner了, 无论是PyCharm还是pip都无法安装成功, 所以只能去 http://tungwaiyip.info/software/HTMLTes ...
- JMeter自学笔记2-图形界面介绍
一.写在前面的话: 上篇我们已经学会了如何安装JMeter和打开JMeter,那么这篇我们将对JMeter的图形界面做一个简单的介绍.大家只要简单的了解即可,无需死记硬背,在今后的学习和使用中慢慢熟悉 ...
- Win10系统XWware虚拟机安装Linux系统(Ubuntu)最新版教程
XWware虚拟机安装Linux系统(Ubuntu)教程 一.下载并安装VMware虚拟机 借助VMware Workstation Pro, 我们可以在同一台Windows或Linux PC上同时运 ...
- 自己来编写一份 Python 脚本 第一版
解决问题 我们已经探索了 Python 语言中的许多部分,现在我们将通过设计并编写一款程序来了解如何把这些部分组合到一起.这些程序一定是能做到一些有用的事情.这节的Python教程就是教大家方法去学习 ...
- 【rich-text】 富文本组件说明
[rich-text] 富文本组件可以显示HTML代码样式. 1)支持事件:tap.touchstart.touchmove.touchcancel.touchend和longtap 2)信任的HTM ...
- java 流 文件 IO
Java 流(Stream).文件(File)和IO Java.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持很多种格式,比如:基本类 ...
- python基本数据类型——元组
元组 元组是一种不可变的序列,创建后不可以修改元素值 # 创建只包含一个元素的元组 >>a = (3,) >>print(a) (3,) #使用 tuple() 转换为元组 & ...