数论算法.线段上的大多数除数
Number theory algorithms. Most divisors on the segment
我正在寻找一个有效的算法来解决以下问题。设d(n)
为n
的正因子个数,其中n
为正整数。我们给定一些1 <= a <= b <= 10^18
,任务是在[a..b]
段上找到d
的最大值,并(可能我们需要更复杂的算法)找到d
的最大值。
前段时间我在免费访问中发现了以下代码:http://ideone.com/qvxPj
unsigned long long n, res;
int p, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 51, 53, 59, 61, 67, 71};
unsigned long long mul(unsigned long long a, unsigned long long b){
unsigned long long res = 0;
while (b){
if (b & 1LL) res = (res + a);
if (res >= n) return 0;
a = (a << 1LL);
b >>= 1LL;
}
return res;
}
void backtrack(int i, int lim, unsigned long long val, unsigned long long r){
if (r > res) res = r;
if (i == p) return;
int d;
unsigned long long x = val;
for (d = 1; d <= lim; d++){
x = mul(x, primes[i]);
if (x == 0) return;
backtrack(i + 1, d, x, r * (d + 1));
}
}
int main(){
p = sizeof(primes) / sizeof(int);
while (scanf("%llu", &n) != EOF){
res = 0;
backtrack(0, 100, 1, 1);
printf("Maximum number of divisors of any number less than %llu = %llun", n, res);
}
return 0;
}
如果有人告诉我它是如何工作的,我会很高兴,因为(对我来说)这个程序运行得非常快。
提前感谢您的帮助。
它像这样遍历所有的数字:
num = P1^D1 * P2^D2 * P3^D3 * ... * Ps^Ds
constraints:
Pi <= 71
1 <= Di <= 100
sequence (Pi) is a sorted list of first s primes
sequence (Di) is nonincreasing
num <= n
让我们检查第一个约束。设最小最优数具有质因数q> 71。若此数中不存在素数p <= 71,则可将q替换为p的同次幂。显然,除数将保持不变,但数量将减少->矛盾。那么没有小于71的未使用素数。但是71以内所有质数的乘积已经非常大了,所以我们考虑的数字必须大于64位n。那是不可能的。
现在让我们解释第二个和第三个约束。假设我们的最小最优数在其分解过程中存在素数q,但不存在素数p,其中p 。然后我们可以用p以相同的顺序替换q,这个数有相同的除数,但会变成less ->矛盾。这意味着在求最优(最小)数的因数分解中,所有质数必须恰好是第一个s质数。所使用的质数集合中不能有漏洞。顺便说一句,Di <= 100是显而易见的,因为即使2^100已经不适合64位整数了。
现在我们必须解释第四个约束。假设D[i] <D[i+1]>对于一些i。然后将P[i]^D[i] * P[i+1]^D[i+1]替换为P[i]^D[i+1] ,数量会变小。例如,将5^2 * 7^3替换为5^3 * 7^2:除数相同,但结果更小。显然,如果我们搜索最小最优数,我们也可以安全地假设这个条件。
现在让我们考虑一下代码。mul
是一个计算a与b乘积的小函数。它是由一个有趣的二进制程序计算出来的。这个过程的主要原因是:如果乘积大于n,则函数返回0。此过程仅用于防止可能发生的溢出。
最后,我们到了backtrack
。这是一个常见的递归搜索。val
是当前数,r
是它的因数数,i
表示我们现在要加的素数的指数,lim
将每个素数的幂限制为100。在最开始,你会看到当前最优答案的更新(存储在res
中),以及硬停止条件(使用所有素数)。
然后有一个循环检查当前质数的每个幂。从幂为1开始,因为幂为0是不允许的。它保持x
中的当前数字,并在每次迭代中将其乘以Pi以增加功率。如果x
大于n,则立即停止。最后,它调用自己来搜索下一个素数
作为@stgatilov答案的补充,我将证明选择将质数限制为小于或等于71的质数
我使用了稍微修改过的代码版本来标记具有最大除数的最大数。对于1000000000000000000或999999999999999999,我得到:
897612484786617600 = 28 * 34 * 52 * 72 * 11 * 13 * 17 * 19 * 23 * 29 * 31 * 37
有103680个总因数。
这意味着对于所有18位的十进制数字,不涉及大于37的质数是找到除数最多的整数
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- 为什么大多数STL算法都需要将排序数据作为输入
- 数论算法.线段上的大多数除数