『学习笔记』蓝书 0x32 约数
定义
若整数 \(n\) 除以整数 \(d\) 的余数为 \(0\),即 \(d\) 能整除 \(n\),则称 \(d\) 是 \(n\) 的约数,\(n\) 是 \(d\) 的倍数,记为 \(d|n\)。
记 \(p_i\) 为质数,\(c_i\) 为指数。
算术基本定理
对于任意大于 \(1\) 的正整数 \(N\),可写作 \(N=p_1^{c_1}p_2^{c_2}\cdots p_m^{c_m}(p_1<p_2<\cdots<p_m)\)。
推论
\(N\) 的正约数集合可写作:\(\lbrace p_1^{b_1}p_2^{b_2}\cdots p_m^{b_m} \rbrace\),其中 \(0 \le b_i \le c_i\)。
\(p_i\) 的指数 \(b_i\) 有 \(c_i+1\) 种可能的取值,则 \(N\) 的正约数个数为
\(N\) 的所有正约数的和为
求正约数集合
试除法
扫描 \(x=1\sim\sqrt N\),判断 \(x\) 是否整除 \(N\)。若能整除,则 \(x\) 与 \(N/x\) 均为 \(N\) 的约束。时间复杂度 \(O(\sqrt N)\)。
推论:\(N\) 的约数个数上限为 \(2\sqrt N\)。
倍数法
若求 \(1\sim N\) 每个数的正约数集合,使用倍数法。
类似筛法,对于正整数 \(x \in [1,N]\),则 \(x,2x,3x,\dots,\lfloor\dfrac{N}{d}\rfloor \times d\) 均含有约数 \(x\)。
时间复杂度 \(O(N+\dfrac{N}{2}+\dfrac{N}{3}+\dots+\dfrac{N}{N})=O(N\log N)\)。
推论: \(1 \sim N\) 每个数的有约数个数总和约为 \(N\log N\)。
P1463 反素数
正整数 \(x\) 约数个数记作 \(g(x)\),若 \(\forall 0<i<x,g(i)<g(x)\),则 \(x\) 为反质数。\(\text{e.g.}\ 1,2,4,6\)
给定 \(N\) 求不超过 \(N\) 的最大反质数。
思路
引理:
-
\(1 \sim N\) 中最大反质数就是 \(1 \sim N\) 中约数个数最多的数中最小的一个。
-
\(1 \sim N\) 中任意数的不同质因子都不会超过 \(10\) 个,且所有质因子指数总和不超过 \(30\)
前 \(11\) 个质数乘积即 \(>2\times 10^9\),且 \(2^{31}>2\times10^9\)。
-
\(\forall x \in [1,N]\),\(x\) 为反质数,则 \(x=2^{c_1} \times 3^{c_2} \times \dots \times 29^{c_{10}}\),且 \(c_1 \ge c_2 \ge \dots \ge c_{10} \ge 0\)。
证明:
若有正整数 \(a\),则对于 \(\forall m,n \in \mathbb{N_+},\forall k \in \mathbb{N}\),\(g(x \times m^k)=g(x \times n^k)=g(a) \times(k+1)\)。
由此,若反质数 \(x\) 存在 \(p_i<p_j,c_i<c_j\),则有 \(x/p_j^{c_j}\times p_i^{c_j}\) 约数个数与 \(x\) 相等,且比 \(x\) 更小。故此时 \(x\) 不是反质数。可得若反质数分解式中存在 \(p_i < p_j\),则必有 \(c_i \ge c_j\)。所以 \(c_i\) 单调不增。
综上,可以 dfs 出前 \(10\) 个质数的指数使其单调递减(引理 \(2,3\))且总乘积不超过 \(N\),按引理 \(1\) 更新答案。
#include <iostream>
using namespace std;
typedef long long ll;
const int inf=0x7fffffff;
int n,mxc,ans=inf;
int p[22]={0,2,3,5,7,11,13,17,19,23,29};
// id: 当前是第几个质数
// x: 用于判断是否为反质数,需小于 n
// cnt: x 的约数个数
// limit: 指数需满足条件
void dfs(int id,ll x,int cnt,int limit){
if(id==11){
if(cnt>mxc || cnt==mxc && x<ans)
mxc=cnt,ans=x;
return;
}
for(int i=0; i<=limit; i++){
if(x>n) return;
dfs(id+1,x,cnt*(i+1),i);
x*=p[id];
}
}
int main(){
scanf("%d",&n);
dfs(1,1,1,inf);
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号