- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
经过一番浏览,我找到了这段代码,用于使用 Eratostenes 筛法在线性时间内计算欧拉的 phi 值。但是未能理解这段代码中使用的主要逻辑,特别是内部 for 循环中所做的事情和使用的想法这个循环用于计算 phi 值。如果有人能帮助我理解这段代码,那将会很有帮助。
#define MAXN 3000000
int phi[MAXN + 1], prime[MAXN/10], sz;
bitset <MAXN + 1> mark;
for (int i = 2; i <= MAXN; i++ ){
if(!mark[i]){
phi[i] = i-1;
prime[sz++]= i;
}
for (int j=0; j<sz && prime[j]*i <= MAXN; j++ ){
mark[prime[j]*i]=1;
if(i%prime[j]==0){
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
else phi[i*prime[j]] = phi[i]*(prime[j]-1 );
}
}
最佳答案
代码既不在这里也不在那里,但算法本身出色。不过,它与埃拉托色尼筛法关系不大。该方法有点让人联想到 Sieve of Sundaram。因为它系统地产生素数的倍数以标记复合物;它比 Sundaram 的更好,因为每个复合 Material 都恰好划掉一次(no overdraw)。同样,每个 phi 值都只计算并分配一次。
如果先稍微改动一下代码会更容易理解:
enum { N = 3000000 };
vector<unsigned> primes;
vector<unsigned> phi(N + 1); // indexed directly with numbers, hence the +1
vector<bool> is_composite(N + 1); // indexed directly with numbers, hence the +1
phi[1] = 1; // phi[0] is 0 already; phi[1] needs to be set explicitly
for (unsigned i = 2; i <= N; ++i)
{
if (not is_composite[i]) // it's a prime
{
phi[i] = i - 1; // a prime is coprime to all numbers before it
primes.push_back(i);
}
for (auto current_prime: primes)
{
unsigned ith_multiple = i * current_prime;
if (ith_multiple > N)
break;
is_composite[ith_multiple] = true;
if (i % current_prime) // i and current_prime are coprime -> phi is multiplicative in this case
{
phi[ith_multiple] = phi[i] * (current_prime - 1); // (current_prime - 1) == phi[current_prime]
}
else
{
phi[ith_multiple] = phi[i] * current_prime; // based on phi(p^(k+1)) / phi(p^k) == p
break;
}
}
}
phi(k) 值的计算必须考虑三种不同的情况:
(1) k 是质数:phi(k) = k - 1,这是平凡的
(2) k = m * p 其中 m 和 p 互质且 p 质数:phi(k) = phi(m * p) = phi(m) * phi(p) = phi(m) * (p - 1)
(3) k = m * p with m = m' * p^n and m' and p coprime and p prime: phi(k) = phi(m) * p
两个相关的数学事实列在 Euler's product formula 下在关于 Euler's totient function 的维基百科文章中.案例1在外循环中处理,案例2是then
内循环条件的分支,案例 3 是 else
也终止内部循环的分支。案例 2 和案例 3 从先前存在的较小数字的 phi 值构建复合 Material 的 phi 值,所有这些最终都来自素数的 phi 值(在外循环中设置)。
该算法的出色之处在于它安排要完成的工作的方式,这样每个值都只计算一次,并且在需要时已经计算过了。它为复合 Material 实现的递归是基于通过分解出其最小素因数来有效地拆分每个复合 Material :m = m' * p。这有助于根据上述情况 2 和 3 计算复合 Material 的 phi,并且它导致生成没有重复的复合 Material 的简单规则。除其他外,外循环将所有可能的 m' 呈现给内循环(尽管对于 i > N/2 内循环从不接受任何并且外循环旋转仅用于收集剩余的素数)。然后,内循环生成所有复合 Material ,这些复合 Material 是 m' 和不超过其自身素数中最小素数的素数的乘积。
代码已根据 list of the first 100,000 phi values 进行了验证从 OEIS page for the phi function 检索.它是专门为展示算法的工作原理而编写的;在程序中使用之前,必须对其进行审查、调整和强化(特别是防止溢出)。
附录 - 以防有人无意中跳过 DanaJ 的评论:is_composite[]
数组是多余的,因为给定的 i
的非复合性(素性)可以通过测试确定phi[i]
在外循环中为零。原因是复合 Material 的 phi 值向上传播 - 它们是在 i
时的早期迭代中计算的。是他们的因素之一。另一种推理方式是 is_composite[m]
仅设置为 true
当计算和存储相应的 phi 值时,这些值永远不会为零。因此,外循环中的测试变为 if (phi[i] == 0)
.实现者(而不是“纯粹的”鉴赏家)可能想更仔细地研究 DanaJ 的评论......
关于c++ - 线性时间欧拉的 Totient 函数计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34260399/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!