值为20,10000,出现错误

时间:2014-03-27 06:06:05

标签: c integer

测试两个32位整数,m的阶乘为m!可以被n整除。如果可以,函数divides()返回1,否则返回0。 如下面的代码,问题是当m = 2010000时,发生了错误。你能解释一下原因吗?

#include <stdio.h>

long factorial(long n){
    if((n == 0) || (n == 1)) return 1;
    else{
    return (n * factorial(n-1));
    }        
}
int divides (long n,long m)
{
    long facN;
    printf("n=%ld ",n);
    facN = factorial(n);
    if(m != 0){
    if(facN == 1) return 0;
        else{
            if(facN % m == 0) return 1;
            else if((facN % m) != 0)return 0;
        }
   }
   else if(m == 0) return 0;
}

int main()
{
    printf("%d", divides(2000000,1));
}

5 个答案:

答案 0 :(得分:2)

您需要计算已考虑模数的阶乘。使用以下标识:

(a * b) % n = ((a % n) * (b % n)) % n

我们可以将阶乘计算为:

m! % n = (((((1 % n) * 2) % n) * 3) % n) ...) % n

答案 1 :(得分:2)

32位整数只能存储0到12的阶乘。

1*2*3*4*5*6*7*8*9*10*11*12
479001600
1*2*3*4*5*6*7*8*9*10*11*12*13
6227020800

答案 2 :(得分:0)

鉴于69!您可能正在查看值溢出,但您可能也会看到内存/堆栈耗尽,因为您将在递归中嵌套200万深度。

您的支票if((facN % m) != 0)也是多余的,因为它在elseif(facN % m == 0)

中被调用

答案 3 :(得分:0)

如果您的原因是要了解m! m是否可以被n整除,请不要计算因子。

而是将n分解为其因素,检查数字中是否有足够多的数字,范围从1m,包括在内。

例如;对于m = 7n = 28,流程应如下所示:

n % 2 == 0 ? yes
n /= 2
2 * 1 <= m ? yes

n % 2 == 0 still? yes
n /= 2
2 * 2 <= m ? yes

n % 2 == 0 still? no

n % 3 == 0 ? no

...

n % 7 == 0 ? yes
n /= 7
7 <= m ? yes

n reached 1, return 1

像这样的东西。如果你无法写出来,那么你可能不应该处理这个问题。不过,如果你愿意,请留下评论,我可以编辑我的答案,以包含一个有效的代码。

我正在添加一个工作示例,使用上面的逻辑来显示n是否是m!的除数,只是为了向您保证这一点确实有效:

#include <stdio.h>

// this function basically compares the powers of the
// prime divisors of factee and divisor
// ... returns 1 if the powers in divisor are
// ... less than or equal to the powers in factee
// ... returns 0 otherwise
int divides( long factee, long divisor ){

    int amount;

    for ( int i = 2; i <= factee; i++ ){

        if ( divisor % i )
            continue;

        amount = 0;
        int copy = factee;
        while ( copy ){
            copy /= i;
            amount += copy;
        }

        while ( divisor % i == 0 ){
            if ( !amount )
                return 0;
            amount--;
            divisor /= i;
        }

        if ( divisor == 1 )
            return 1;
    }

    return 0;
}

int main( )
{
    printf( "%d", divides( 20, 10000 ) );

    getchar( );
    return 0;
}

amount变量计算im!的数量。在计算它的while循环中,在第一个循环中添加i s的数量,然后在第二个循环中添加i * i s的数量,并且等等,直到没有。

例如,对于m = 5i = 2m / 22,这是{{1}内因子2的出现次数}}。然后5! m / 2 / 21内因子2 * 2 == 4的出现次数。然后5!m / 2 / 2 == 0的计数,这会导致循环因2 * 2 * 2 == 8遭遇而结束。

修改

我在代码中修复了一些重要内容,删除了最外层的0,这是我在开始时放的东西,显然忘了删除,导致潜在的无限循环。在这里,我还制作了一个功能的改进版本,通常比上面的版本运行得更快:

while

答案 4 :(得分:-1)

long可以支持-2,147,483,647到2,147,483,647范围内的值,这里2000000!超出了长期的范围,这就是显示错误的原因。