|
|
|
@ -1,3 +1,4 @@
|
|
|
|
|
|
|
|
|
|
## 莫比乌斯函数
|
|
|
|
|
|
|
|
|
|
**[【数论】为什么莫比乌斯函数长这样?这样理解最自然!](https://www.bilibili.com/video/BV165411G7v3)**
|
|
|
|
@ -6,39 +7,14 @@
|
|
|
|
|
|
|
|
|
|
https://blog.csdn.net/qq_49593247/article/details/120394226
|
|
|
|
|
|
|
|
|
|
https://www.cnblogs.com/letlifestop/p/10262757.html
|
|
|
|
|
|
|
|
|
|
// https://blog.csdn.net/qq_42887171/article/details/95237740
|
|
|
|
|
### 一、莫比乌斯函数
|
|
|
|
|
|
|
|
|
|
要学习莫比乌斯函数需要学习 到 **积性函数**,深度理解 **欧拉筛** 。
|
|
|
|
|
先明确一点,莫比乌斯函数并不是什么很高大上的东西,它其实只是一个由容斥系数所构成的函数。
|
|
|
|
|
|
|
|
|
|
### 一、积性函数
|
|
|
|
|
**[视频讲解:两分钟学会墨比乌斯函数](https://www.bilibili.com/video/BV12P4y1Q7tc/)**
|
|
|
|
|
|
|
|
|
|
#### 1. 定义
|
|
|
|
|
|
|
|
|
|
**积性函数**:若$gcd(a,b)=1$,且满足$f(a*b)=f(a)*f(b)$,则称$f(x)$为 **积性函数**
|
|
|
|
|
|
|
|
|
|
**完全积性函数**:对于任意正整数$a,b$,都满足$f(a*b)=f(a)*f(b)$,则称$f(x)$为 **完全积性函数**
|
|
|
|
|
|
|
|
|
|
#### 2. 性质
|
|
|
|
|
|
|
|
|
|
1. 若$f(n),g(n)$均为积性函数,则函数$h(n)=f(n)*g(n)$也是积性函数
|
|
|
|
|
|
|
|
|
|
2. 若$f(n)$为积性函数,则函数$c*f(n)$($c$是常数)也是积性函数,反之一样
|
|
|
|
|
|
|
|
|
|
3. **任何积性函数都能应用线性筛**,在$O(n)$时间内求出$1\sim n$项(**莫比乌斯函数要用到**),像素数,欧拉函数等都是 **积性函数**。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 二、莫比乌斯函数
|
|
|
|
|
|
|
|
|
|
#### 1. 用途
|
|
|
|
|
|
|
|
|
|
我们举例一道经典的应用题,求$1$到$N$中与$a$互质的数的个数:根据容斥原理,设$S_i$为$1$到$N$中和$a$有公因子$i$的数的个数,答案为$N−S_2-S_3-S_5-S_7...+S_{2,3}+S_{3,5}+S_{2,5}...$,可以发现,其答案为$\large \displaystyle \sum_{i=1}^{N}\mu(i)*S_i$。
|
|
|
|
|
|
|
|
|
|
> **注**:在使用容斥原理解决计数问题时,莫比乌斯函数的值就是每一项的系数,要么是$1$,要么是$-1$。这是因为莫比乌斯函数在容斥原理中的作用就是用来表示每个子集合的权重,从而在计算中起到排除重复计数的作用。
|
|
|
|
|
|
|
|
|
|
#### 2. 定义
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
莫比乌斯函数是个分段函数,它的意思:
|
|
|
|
@ -55,169 +31,247 @@ https://www.cnblogs.com/letlifestop/p/10262757.html
|
|
|
|
|
函数值 1 -1 -1 0 -1 1 -1 0 0 1 -1 0 -1 1 1 0 -1 0 -1 0
|
|
|
|
|
数 字: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 2. 用途
|
|
|
|
|
|
|
|
|
|
我们举例一道经典的应用题,求$1$到$N$中与$a$互质的数的个数:根据容斥原理,设$S_i$为$1$到$N$中和$a$有公因子$i$的数的个数,答案为$N−S_2-S_3-S_5-S_7...+S_{2,3}+S_{3,5}+S_{2,5}...$,可以发现,其答案为$\large \displaystyle \sum_{i=1}^{N}\mu(i)*S_i$。
|
|
|
|
|
|
|
|
|
|
> **注**:在使用容斥原理解决计数问题时,莫比乌斯函数的值就是每一项的系数,要么是$1$,要么是$-1$。这是因为莫比乌斯函数在容斥原理中的作用就是用来表示每个子集合的权重,从而在计算中起到排除重复计数的作用。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### 3. 求单个数字的莫比乌斯函数值
|
|
|
|
|
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
//单个数的莫比乌斯函数
|
|
|
|
|
int getmob(LL x) {
|
|
|
|
|
// 单个数的莫比乌斯函数
|
|
|
|
|
int getmob(int x) {
|
|
|
|
|
int sum = 0;
|
|
|
|
|
for (LL i = 2; i <= x / i; i++) { //从2开始,一直到 sqrt(x),枚举所有可能存的小因子
|
|
|
|
|
for (int i = 2; i <= x / i; i++) { // 从2开始,一直到 sqrt(x),枚举所有可能存的小因子
|
|
|
|
|
int cnt = 0;
|
|
|
|
|
if (x % i == 0) { //如果x可以整除i
|
|
|
|
|
while (x % i == 0) cnt++, x /= i; //计数,并且不断除掉这个i因子
|
|
|
|
|
if (cnt > 1) return 0; //如果某个因子,存在两个及以上个,则返回0
|
|
|
|
|
sum++; //记录因子个数
|
|
|
|
|
if (x % i == 0) { // 如果x可以整除i
|
|
|
|
|
while (x % i == 0) cnt++, x /= i; // 计数,并且不断除掉这个i因子
|
|
|
|
|
if (cnt > 1) return 0; // 如果某个因子,存在两个及以上个,则返回0
|
|
|
|
|
sum++; // 记录因子个数
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (x != 1) sum++; //如果还存在另一个大因子,那么因子个数+1
|
|
|
|
|
return (sum & 1) ? -1 : 1; //奇数个因子,返回-1,否则返回1
|
|
|
|
|
if (x != 1) sum++; // 如果还存在另一个大因子,那么因子个数+1
|
|
|
|
|
return (sum & 1) ? -1 : 1; // 奇数个因子,返回-1,否则返回1
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 4.枚举倍数求莫比乌斯函数(埃氏筛)
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
//枚举倍数求莫比乌斯函数
|
|
|
|
|
LL mu[N] , sum[N];
|
|
|
|
|
void mobius(LL x) {
|
|
|
|
|
mu[1] = 1;
|
|
|
|
|
for (LL i = 1; i <= x; i++)
|
|
|
|
|
for (LL j = i + i; j <= x; j += i)
|
|
|
|
|
mu[j] -= mu[i];
|
|
|
|
|
// 维护u(x)前缀和
|
|
|
|
|
for (LL i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.枚举约数求莫比乌斯函数(欧拉筛)
|
|
|
|
|
#### 4.欧拉筛扩展求莫比乌斯函数
|
|
|
|
|
**[视频讲解](https://www.bilibili.com/video/BV1Te4y1C7DP)**
|
|
|
|
|
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
LL mu[N] , sum[N];
|
|
|
|
|
// 筛法求莫比乌斯函数(枚举约数)
|
|
|
|
|
int mu[N], sum[N]; // sum[N]:梅滕斯函数,也就是莫比乌斯函数的前缀和
|
|
|
|
|
int primes[N], cnt;
|
|
|
|
|
bool st[N];
|
|
|
|
|
void get_mobius2(LL n) {
|
|
|
|
|
void get_mobius(int n) {
|
|
|
|
|
mu[1] = 1;
|
|
|
|
|
for (LL i = 2; i <= n; i++) {
|
|
|
|
|
for (int i = 2; i <= n; i++) {
|
|
|
|
|
if (!st[i]) {
|
|
|
|
|
primes[cnt++] = i;
|
|
|
|
|
mu[i] = -1;
|
|
|
|
|
}
|
|
|
|
|
for (LL j = 0; primes[j] <= n / i; j++) {
|
|
|
|
|
LL t = primes[j] * i;
|
|
|
|
|
for (int j = 0; primes[j] <= n / i; j++) {
|
|
|
|
|
int t = primes[j] * i;
|
|
|
|
|
st[t] = true;
|
|
|
|
|
if (i % primes[j] == 0) {
|
|
|
|
|
mu[t] = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
mu[t] = mu[i] * -1;
|
|
|
|
|
mu[t] = -mu[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 维护u(x)前缀和
|
|
|
|
|
for (LL i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
|
|
|
|
|
// 维护u(x)前缀和:梅滕斯函数
|
|
|
|
|
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 6、性质$I$
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
该图意为$n$的所有因子的莫比乌斯值的和只有在$n=1$时成立为$1$,其余通通为$0$;
|
|
|
|
|
### 二、题单
|
|
|
|
|
**[$SP4168$ $SQFREE$ - $Square$-$free$ $integers$](https://www.luogu.com.cn/problem/SP4168)**
|
|
|
|
|
|
|
|
|
|
对这个性质的证明:
|
|
|
|
|
**题意**
|
|
|
|
|
在数论中,如果一个整数不能被任何一个整数(这个整数不是$1$)的平方整除,我们就称它是一个$Square−freeinteger$(**无平方数因数的数**)。你得数一数!
|
|
|
|
|
|
|
|
|
|
首先我们可以把$n$分解为很多个质数相乘(此时质数的幂不一定为$1$):
|
|
|
|
|
令 $\large n=p_1^ {a_1}* p_2^ {a_2}* ... *p_k^{a_k}$
|
|
|
|
|
求出$1 \sim n$ 中无平方因子数的个数。
|
|
|
|
|
|
|
|
|
|
$\displaystyle \sum_{d | n} \mu(d)$ 这是求$n$的所有约数的莫比乌斯函数值的和,相当于在$p_1,p_2,p_3,...$这些素数中选择若干个质因子相乘来组成所有约数。
|
|
|
|
|
**题解**
|
|
|
|
|
|
|
|
|
|
根据莫比乌斯函数性质,包含有素数平方的约数不用计算,他对答案的贡献值为$0$,所以我们可以把$n$分解的质数的次数全部消除为$1$,只有当莫比乌斯值为$-1$或者$1$时才对结果有贡献.那么问题就单纯的变为在$k$个$n$的质因子中选$0$到$k$个值组成约数,再将这些约数的值相加:
|
|
|
|
|
先来求一下 **平方数因数** 的数有多少个:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
在$[1, n]$ 中,有多少个数是$x^2$的倍数? 显然是$⌊\frac{n}{x^2}⌋$个。
|
|
|
|
|
|
|
|
|
|
注意,这里的符号并不是全为加法,而是隔一个加隔一个减,这是因为莫比乌斯函数是积性函数,当选的数是奇数个时为值为负,反之为正,又因二项式定理,将$-1$和$1$带入,可以得到结果为$0$.
|
|
|
|
|
那 $⌊\frac{n}{x^2}⌋$ 就是答案了吗?当然不是,有大量的数被重复计算了。
|
|
|
|
|
|
|
|
|
|
例如 $36$,它等于$2^2\times 3^2$ ,在计算 $2$ 和 $3$ 的时候它会被重复计算。
|
|
|
|
|
|
|
|
|
|
怎么办呢?
|
|
|
|
|
|
|
|
|
|
#### 7、性质$II$
|
|
|
|
|
对任意正整数$n$
|
|
|
|
|

|
|
|
|
|
利用容斥思想,$1$到$n$以内有平方因数的数有$\large \frac{n}{2^2}+\frac{n}{3^2}+\frac{n}{5^2}-\frac{n}{6^2}...$。
|
|
|
|
|
> **注**:
|
|
|
|
|
> ① 为什么没有$4^2,8^2$呢?这是因为$4^2=4 \times 2^2,8^2=16\times 2^2$,在计算$2^2$的个数时,已经计算过了,同理,合数都可以拆分成质数的乘积,我们只要计算质数的平方就可以了。
|
|
|
|
|
② 但是 $6^2=2^2\times 3^2$这样的数字比较特殊,它会被在计算$2^2$时计算一遍,在计算$3^2$时又计算了一遍,计算重复了,需要再扣除掉$\frac{n}{6^2}$个,这里可以看出来符合容斥原理。
|
|
|
|
|
|
|
|
|
|
($ps$:这条涉及莫比乌斯反演,还没学,学了再看)
|
|
|
|
|
**$Q$:即然这是容斥原理,和莫比乌斯函数有什么关系?**
|
|
|
|
|
答:从现实意义上去看看:
|
|
|
|
|
- $2,3,5$都是一个质数因子,它的系数是$1$
|
|
|
|
|
- $4=2^2$,按莫比乌斯函数的说法,系数为$0$,无贡献
|
|
|
|
|
- $6 = 2 \times 3$,有两个质数因子,系数是$-1$
|
|
|
|
|
|
|
|
|
|
#### 题单
|
|
|
|
|
**[完全平方数](https://www.luogu.com.cn/problem/P4318)**
|
|
|
|
|
这不就是莫比乌斯函数的定义吗?
|
|
|
|
|
|
|
|
|
|
题意就是筛去完全平方数及其的倍数,然后输出第k个的值.
|
|
|
|
|
可知以上式子 $\displaystyle =-\sum_{2 \leq d \leq \sqrt{n}} \mu(d)*⌊\frac{n}{d^2}⌋$
|
|
|
|
|
> **注**:为什么只枚举到$\sqrt{n}$,而不是到$n$呢?这是因为:$d>\sqrt{n}$时,$⌊\frac{n}{d^2}⌋$恒等于$0$,再继续也是无贡献,只需要枚举到$\sqrt{n}$即可。
|
|
|
|
|
|
|
|
|
|
我们要求这个,就想到把1到ki的所有完全平方数和他的倍数筛去,但是一看数据,1e9,线性筛必定t,那再去想办法进行计算,我们先把2的平方4的倍数计算出来,在1到ki中,有ki/4个4的倍数,我们再计算的16的倍数个数时候,会发现在计算4的倍数个数时候已经把16的倍数个数计算过了,这里就重复了,而假设已经计算了4和9的倍数个数,再去计算36的倍数个数就会发现计算了两次,那么就要减去36的倍数个数,这里就已经想到可以用容斥了.这里我们发现这里需要枚举质数的平方的次数,且奇数偶数符号不相同,就会想到莫比乌斯函数.它计算枚举的边界是i*i<=n;我们再用n减去计算的出来的从2开始的到ki的完全平方数的个数即为所求:
|
|
|
|
|
所以无平方因数的数就是 **求补集**=$\displaystyle n-(-\sum_{2 \leq d \leq \sqrt{n}} \mu(d)*⌊\frac{n}{d^2}⌋)=n+\sum_{2 \leq d \leq \sqrt{n}} \mu(d)*⌊\frac{n}{d^2}⌋$个。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
变形合并,$d=1,\mu(d)=1$(莫比乌斯的分段函数求得)
|
|
|
|
|
$\mu(d)*⌊\frac{n}{d^2}⌋=\mu(1)*(n/1^2)=1*n=n$
|
|
|
|
|
|
|
|
|
|
当求出来之后,我们就可以用二分来求此时的值:
|
|
|
|
|
此时可以发现这个式子,第一项也可以合并进来,合并成
|
|
|
|
|
$$\displaystyle \sum_{1 \leq d \leq \sqrt{n}} \mu(d)*⌊\frac{n}{d^2}⌋$$
|
|
|
|
|
|
|
|
|
|
$⌊\frac{n}{d^2}⌋$是整除分块的基本形式,用整除分块优化,区间的数值都是一样的,但每项的符号有加有减,一个个算太慢了,可以给$μ(x)$预处理出前缀和,这样直接用$O(1)$时间计算前缀和,再乘上整除分块的数值就行了~
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### $Code$
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include<iostream>
|
|
|
|
|
#define ll long long
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
using namespace std;
|
|
|
|
|
int vis[40560],mo[40560],p[4253],n;
|
|
|
|
|
void init()
|
|
|
|
|
{
|
|
|
|
|
int tot=0,k;
|
|
|
|
|
mo[1]=1;
|
|
|
|
|
for(int i=2;i<=40559;i++)
|
|
|
|
|
{
|
|
|
|
|
if(vis[i]==0)
|
|
|
|
|
{
|
|
|
|
|
p[++tot]=i;
|
|
|
|
|
mo[i]=-1;
|
|
|
|
|
#define int long long
|
|
|
|
|
#define endl "\n"
|
|
|
|
|
const int M = 110; // 询问次数
|
|
|
|
|
const int N = 10000010; // 莫比乌斯函数值的极限数据上限,sqrt(1e14)=1e7
|
|
|
|
|
int n, sqrtN; // T次询问,每次都是1~n,sqrtN=sqrt(max(n)),真实上限
|
|
|
|
|
int q[M]; // T次询问,用q数组记录下来
|
|
|
|
|
|
|
|
|
|
// 筛法求莫比乌斯函数(枚举约数)
|
|
|
|
|
int mu[N], sum[N]; // sum[N]:梅滕斯函数,也就是莫比乌斯函数的前缀和
|
|
|
|
|
int primes[N], cnt;
|
|
|
|
|
bool st[N];
|
|
|
|
|
void get_mobius(int n) {
|
|
|
|
|
mu[1] = 1;
|
|
|
|
|
for (int i = 2; i <= n; i++) {
|
|
|
|
|
if (!st[i]) {
|
|
|
|
|
primes[cnt++] = i;
|
|
|
|
|
mu[i] = -1;
|
|
|
|
|
}
|
|
|
|
|
for(int j=1;j<=tot&&(k=i*p[j])<=40559;j++)
|
|
|
|
|
{
|
|
|
|
|
vis[k]=1;
|
|
|
|
|
if(i%p[j]!=0)mo[k]=-mo[i];
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mo[k]=0;
|
|
|
|
|
for (int j = 0; primes[j] <= n / i; j++) {
|
|
|
|
|
int t = primes[j] * i;
|
|
|
|
|
st[t] = true;
|
|
|
|
|
if (i % primes[j] == 0) {
|
|
|
|
|
mu[t] = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
mu[t] = -mu[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 维护u(x)前缀和:梅滕斯函数
|
|
|
|
|
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
|
|
|
|
|
}
|
|
|
|
|
bool judge(int x)
|
|
|
|
|
{
|
|
|
|
|
ll ans=0;int i;
|
|
|
|
|
for(int i=1;i*i<=x;i++)
|
|
|
|
|
{
|
|
|
|
|
ans+=mo[i]*(x/(i*i));
|
|
|
|
|
|
|
|
|
|
signed main() {
|
|
|
|
|
#ifndef ONLINE_JUDGE
|
|
|
|
|
freopen("SQP4168.in", "r", stdin);
|
|
|
|
|
#endif
|
|
|
|
|
int T;
|
|
|
|
|
cin >> T;
|
|
|
|
|
for (int i = 1; i <= T; i++) {
|
|
|
|
|
cin >> q[i];
|
|
|
|
|
n = max(n, q[i]); // 找到最大的n,这样可以避免重复计算
|
|
|
|
|
}
|
|
|
|
|
sqrtN = sqrt(n); // 最大的n,只需要枚举到sqrt(n)即可
|
|
|
|
|
// 对有效范围内的数字求莫比乌斯函数
|
|
|
|
|
get_mobius(sqrtN); // 线性求莫比乌斯函数, 前缀和
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= T; i++) { // 离线处理,对于每个询问进行回答
|
|
|
|
|
n = q[i]; // 第i次的n值
|
|
|
|
|
int ans = 0; // 初始化返回结果
|
|
|
|
|
for (int l = 1, r; l <= n; l = r + 1) { // 整除分块
|
|
|
|
|
if (n / (l * l) == 0) break;
|
|
|
|
|
// n / (l * l): 分块的左边界是l,值是n/(l*l),如果n<(l*l)时,l再长大也没用,也都是0
|
|
|
|
|
// n/(l*l):整除分块中整个分块内的个数值,从n/(l*l)~n/(r*r)是同一个值
|
|
|
|
|
r = sqrt(n / (n / (l * l))); // 求出右边界r
|
|
|
|
|
ans += n / (l * l) * (sum[r] - sum[l - 1]); // 利用莫比乌斯函数值前缀和求块的贡献
|
|
|
|
|
}
|
|
|
|
|
cout << ans << endl;
|
|
|
|
|
}
|
|
|
|
|
if(ans>=n)return true;
|
|
|
|
|
else return false;
|
|
|
|
|
}
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
int t;
|
|
|
|
|
ll l,r,mid;
|
|
|
|
|
init();
|
|
|
|
|
scanf("%d",&t);
|
|
|
|
|
while(t--)
|
|
|
|
|
{
|
|
|
|
|
scanf("%d",&n);
|
|
|
|
|
l=n,r=1644934082;
|
|
|
|
|
while(l<r)
|
|
|
|
|
{
|
|
|
|
|
// cout<<l<<" oo "<<r<<endl;
|
|
|
|
|
mid=(l+r)>>1;
|
|
|
|
|
if(judge(mid))
|
|
|
|
|
r=mid;
|
|
|
|
|
else l=mid+1;
|
|
|
|
|
}
|
|
|
|
|
printf("%lld\n",r);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**[$P4318$ 完全平方数](https://www.luogu.com.cn/problem/P4318)**
|
|
|
|
|
|
|
|
|
|
**题意**
|
|
|
|
|
小$X$自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而这丝毫不影响他对其他数的热爱。
|
|
|
|
|
|
|
|
|
|
这天是小$X$的生日,小$W$想送一个数给他作为生日礼物。当然他不能送一个小$X$讨厌的数。他列出了所有小$X$不讨厌的数,然后选取了第$K$个数送给了小$X$。小$X$很开心地收下了。
|
|
|
|
|
|
|
|
|
|
然而现在小$W$却记不起送给小$X$的是哪个数了。你能帮他一下吗?
|
|
|
|
|
|
|
|
|
|
**解法**
|
|
|
|
|
设$f(n)$表示在$1$到$n$中小$X$不讨厌的数的数量。显然$f(n)$是 **单调递增** 的,所以我们可以二分答案。
|
|
|
|
|
> **注**: 与上一题的区别在于上一题明确给出了最大值$n$,也就是右边界的范围,本题没有告诉我们范围,需要我们自己找到右边界。随着右边界越来越大,肯定符合条件的数字个数也会越来越多,也就是上面说到的单调性。我们可以用二分来假设一个右边界,然后不断的收缩区间来找到准备的右边界:在上道题的基础上加上二分,判断$1$到$mid$是否有$K$个无平方因子的数,以此改变左右边界即可。
|
|
|
|
|
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
using namespace std;
|
|
|
|
|
#define int long long
|
|
|
|
|
#define endl "\n"
|
|
|
|
|
const int N = 100010;
|
|
|
|
|
|
|
|
|
|
// 筛法求莫比乌斯函数(枚举约数)
|
|
|
|
|
int mu[N];
|
|
|
|
|
int primes[N], cnt;
|
|
|
|
|
bool st[N];
|
|
|
|
|
void get_mobius(int n) {
|
|
|
|
|
mu[1] = 1;
|
|
|
|
|
for (int i = 2; i <= n; i++) {
|
|
|
|
|
if (!st[i]) {
|
|
|
|
|
primes[cnt++] = i;
|
|
|
|
|
mu[i] = -1;
|
|
|
|
|
}
|
|
|
|
|
for (int j = 0; primes[j] <= n / i; j++) {
|
|
|
|
|
int t = primes[j] * i;
|
|
|
|
|
st[t] = true;
|
|
|
|
|
if (i % primes[j] == 0) {
|
|
|
|
|
mu[t] = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
mu[t] = -mu[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int check(int mid, int k) {
|
|
|
|
|
int res = 0;
|
|
|
|
|
for (int i = 1; i * i <= mid; i++) // 枚举范围内每个平方数
|
|
|
|
|
res += mu[i] * (mid / i / i);
|
|
|
|
|
return res >= k;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
signed main() {
|
|
|
|
|
// 获取莫比乌斯函数值
|
|
|
|
|
get_mobius(N - 1);
|
|
|
|
|
|
|
|
|
|
int T, k;
|
|
|
|
|
cin >> T; // T组测试数据
|
|
|
|
|
while (T--) {
|
|
|
|
|
cin >> k; // 第k个数
|
|
|
|
|
int l = 1, r = 2e9;
|
|
|
|
|
while (l < r) {
|
|
|
|
|
int mid = l + r >> 1;
|
|
|
|
|
if (check(mid, k))
|
|
|
|
|
r = mid;
|
|
|
|
|
else
|
|
|
|
|
l = mid + 1;
|
|
|
|
|
}
|
|
|
|
|
cout << r << endl;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
例题:数字染色
|
|
|
|
|
#### 例题:数字染色
|
|
|
|
|
题目意思:
|
|
|
|
|
|
|
|
|
|
给一个数组,在其中选数,看可以最多选出多少个gcd(最大公约数)>1的集合.
|
|
|
|
@ -295,6 +349,9 @@ int main()
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
ps:最后结果防止取模出负数要加上mod再取模.
|
|
|
|
|
|
|
|
|
|
之后会继续学习莫比乌斯反演的,如果本蒟蒻有什么错误望大佬指正.
|
|
|
|
|
https://blog.csdn.net/qq_49593247/article/details/120394226
|
|
|
|
|
|
|
|
|
|
https://www.cnblogs.com/letlifestop/p/10262757.html
|
|
|
|
|
|
|
|
|
|
// https://blog.csdn.net/qq_42887171/article/details/95237740
|
|
|
|
|