【问题标题】:Anomaly in program related to legendre's formula与legendre公式相关的程序异常
【发布时间】:2020-03-21 13:29:30
【问题描述】:

首先,我要澄清一下,我是编程新手,最近开始接触 c++。我的数学课本里有一个与勒让德公式有关的问题,我想制作一个与之相关的程序。它从用户 n 中获取一个数字,并找到 n 的最大幂除以 n!

它对于很多数字都运行良好,但对于其他一些数字来说却是混乱的,而且它是完全随机的。这是代码中的一个sn-p。

#include <iostream>
#include <math.h>

using namespace std;

int prime(int);
int calc(int, int);
int main()
{
    int n;
    int hpf=2;
    cout<<"This program finds highest power x that divides x!"<<endl;
    cout << "Enter number : " << endl;
    cin>>n;
    for(int i=2; i<=n; i++)
    {
        bool p=prime(i);
        if(p==true && n%i==0)
            hpf=i;
    }
    cout<<"The highest prime factor of the number is : "<<hpf<<endl;
    int p=calc(hpf, n);
    cout<<"The highest power of "<<n<<" that divides "<<n<<"!"<<" is : "<<p;
    return 0;
}

calc(int f, int n)
{
    int c=0 , d=1, power=1, i=0;
    while(i>=0)
    {
        int x= pow(f,power+i);
        if(i>0 && n%x==0)
            d++;
        if(x<=n)
        {
            c+=n/x;
            i++;
        }
        else
            break;
    }
    return c/d;
}

prime(int n)
{
   bool isPrime = true;
   for(int i = 2; i <= n/2; i++)
    {
      if (n%i == 0)
      {
         isPrime = false;
         break;
      }
    }
   return isPrime;
}

我将 n 的最高质因数和数字 n 本身传递给 int calc(int, int)。

现在问题来了:

当我输入 n=9 时,我得到

Enter number :
9
The highest prime factor of the number is : 3
The highest power of 9 that divides 9! is : 2

另一方面,如果我输入 25,我得到

Enter number :
25
The highest prime factor of the number is : 5
The highest power of 25 that divides 25! is : 6

这显然是错误的,最高的应该是3。

它也可以准确地处理更大的数字,但不是全部。

PS:我使用代码块。

【问题讨论】:

  • 您可能想检查int 在您的平台上可以容纳的最大数字是多少,看看是否是 25!适合int。我的猜测是你运气不好。 numeric_limits/max
  • 25!也不适合 64 位变量。
  • 另外请记住,pow 是一个双精度浮点函数,因此可能不完全准确(并且不能准确表示大的 64 位整数)。
  • 是的,可能。或者至少,如果可以的话,Minimal, Reproducible Example
  • 至于奇普斯特的评论:最大因子不会大于n / 2,但你只需要检查i*i &lt;= n的数字,因为如果n可以被i整除表示i*j == n。现在i 将小于sqrt(n) 并且j 将大于除非n 是正方形并且i == j。但请注意:sqrt() 也是一个浮点函数,可能与pow 有类似的问题...

标签: c++ c


【解决方案1】:

我不确定为什么它确实适用于 9 而不是 25(您的程序看起来不错,但是当您计算 d 或其他东西时可能会遇到问题),尽管两者都是素数的平方并且您的代码似乎需要关心这个,但我知道为什么它不适用于像 12 这样的数字。发生这种情况是因为你的代码只查看最高的素数而忽略其他的。当其他素数出现的频率低于最大的素数时,这将为您提供真实的结果,但在所有其他情况下,这种假设会导致错误的结果,因为最高的素数也会受到较小素数的限制。因此,正确的解决方案必须考虑所有主要因素。

为此,您首先需要对数字进行因式分解(获取质因数及其幂!)。如果您不确定如何执行此操作,您可以谷歌搜索。我不想在这里包含它,因为那样答案会很长。

然后您需要找出该数字在阶乘中出现的频率。 正如您已经知道的(至少您在代码中使用了它),您可以通过将出现次数总结为阶乘的每个因子中每个素数的幂的因子来计数,这可以通过这样的除法来完成:

n/p¹ + n/p² + n/p³ + n/p⁴ + …

这可以放入一个简单的函数中(使用简单的自制功率计算):

int occurenceInFaculty(int factor, int faculty) {
    int sum = 0;
    for(int power = factor; power <= faculty; power *= factor) { // Go through all powers
        sum += faculty/power;
    }
    return sum;
}

现在您可以计算数字中每个素因数的出现次数,如果除以因式分解中该素因数的幂,您将得到最高幂的上限。 然后剩下要做的就是在所有主要因素上取最小值,你就完成了。 假设在此处存储质因数分解的一种可能方式是生成的代码可能如下所示:

代码开头的某处:

typedef struct {
    int prime;
    int power;
} PrimeFactor;

假设这样的素数分解方法:

PrimeFactor* factorization(int number, int* factors) {
    // Factorize here. Return a pointer to an array of PrimeFactors and set the pointer factors to the arrays length.
}

然后是计算部分:

int number = 25; // Put your number here.
int length = 0;
PrimeFactor* factors = factorization(25, &length);
int min = number; // Some reasonable upper border because n! < n^n
for(int i = 0; i < length; i++) {
    if(occurenceInFaculty(factors[i].prime, number)/factors[i].power < min)
        min = occurenceInFaculty(factors[i].prime, number)/factors[i].power;
}

这个程序也得到了 25 对!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多