C 计算n!m不是素数时的mod m

C 计算n!m不是素数时的mod m,c,algorithm,math,modulus,C,Algorithm,Math,Modulus,我读过很多计算n的好算法!mod m,但当m为素数时,它们通常有效。我想知道当m不是素数时是否存在一些好的算法。如果有人也能编写算法的基本函数,我会很有帮助。我一直在使用 long long factMOD(long long n,long long mod) { long long res = 1; while (n > 0) { for (long long i=2, m=n%mod; i<=m; i++) res = (

我读过很多计算n的好算法!mod m,但当m为素数时,它们通常有效。我想知道当m不是素数时是否存在一些好的算法。如果有人也能编写算法的基本函数,我会很有帮助。我一直在使用

long long factMOD(long long n,long long mod)
{
    long long res = 1; 
    while (n > 0)
    {
        for (long long i=2, m=n%mod; i<=m; i++)
        res = (res * i) % mod;
        if ((n/=mod)%2 > 0) 
        res = mod - res;
    }
    return res;
}
long-long-factMOD(long-long n,long-long-mod)
{
长res=1;
而(n>0)
{
对于(长i=2,m=n%mod;i 0)
res=mod-res;
}
返回res;
}
但当我试图打印factMOD(4,3)时,得到了错误的答案。此算法的来源是:

基本算法对
m的任何值都有效:

product := 1
for i := 2 to n
    product := (product * i) mod m
return product

一个简单的优化是,只要
product
变为0,就可以提前退出并返回0。如果n>m,您也可以在开始时返回0,因为这保证了n!是m的倍数。

基本算法对
m的任何值都有效:

product := 1
for i := 2 to n
    product := (product * i) mod m
return product

一个简单的优化是,只要
product
变为0,就可以提前退出并返回0。如果n>m,您也可以在开始时返回0,因为这保证了n!是m的倍数。

这就是我得出的结论:

#include <stdio.h>
#include <stdlib.h>

unsigned long long nfactmod(unsigned long long n, unsigned long long m)
{
    unsigned long long i, f;
    for (i = 1, f = 1; i <= n; i++) {
        f *= i;
        if (f > m) {
            f %= m;
        }
    }
    return f;
}

int main(int argc, char *argv[])
{
    unsigned long long n = strtoull(argv[1], NULL, 10);
    unsigned long long m = strtoull(argv[2], NULL, 10);

    printf("%llu\n", nfactmod(n, m));

    return 0;
}

在几分之一秒内运行。

这就是我想到的:

#include <stdio.h>
#include <stdlib.h>

unsigned long long nfactmod(unsigned long long n, unsigned long long m)
{
    unsigned long long i, f;
    for (i = 1, f = 1; i <= n; i++) {
        f *= i;
        if (f > m) {
            f %= m;
        }
    }
    return f;
}

int main(int argc, char *argv[])
{
    unsigned long long n = strtoull(argv[1], NULL, 10);
    unsigned long long m = strtoull(argv[2], NULL, 10);

    printf("%llu\n", nfactmod(n, m));

    return 0;
}


在几分之一秒内运行。

只需执行mod m的所有乘法运算-这不会很困难。-当乘法结果大于
m
时,取模
m
@mvp-n,数量级为10^7。我需要一个更好的算法来实现。你考虑过使用链式模的算法吗<代码>(a*b)mod p=((a mod p)*(b mod p))mod p
。这可以很好地帮助你解决你的问题,特别是当你遇到零的时候,提前退出捷径。@WhozCraig这实际上已经尽可能多地做到了;只是有点含蓄。乘法的左侧是正在运行的乘积,它已经是mod-m了;如果你应用任何一个早期的退出优化,乘法的右边应该已经小于m,这意味着取mod m是不可行的。只需执行mod m的所有乘法-这不会很困难。-当乘法结果大于
m
时,取模
m
@mvp-n,数量级为10^7。我需要一个更好的算法来实现。你考虑过使用链式模的算法吗<代码>(a*b)mod p=((a mod p)*(b mod p))mod p
。这可以很好地帮助你解决你的问题,特别是当你遇到零的时候,提前退出捷径。@WhozCraig这实际上已经尽可能多地做到了;只是有点含蓄。乘法的左侧是正在运行的乘积,它已经是mod-m了;如果你应用任何一个早期的退出优化,乘法的右边应该已经小于m,这意味着取mod m是不可行的。这个算法不足以解决我的问题。我被赋予了接近10^7的n。这将大大超过时间限制。@kavish:你试过实现它吗?对于我来说,Python是一种速度相对较慢的语言,它几乎可以立即运行。@kavish 10^7不是一个很大的数字。@kavish您尝试过这个算法来检查它是否满足您的时间限制吗?@kavish看到我的答案了吗。我已经实现了几乎完全相同的算法(没有霍布斯提出的优化),但它立即为我运行
n=1000000
…这个算法不足以解决我的问题。我被赋予了接近10^7的n。这将大大超过时间限制。@kavish:你试过实现它吗?对于我来说,Python是一种速度相对较慢的语言,它几乎可以立即运行。@kavish 10^7不是一个很大的数字。@kavish您尝试过这个算法来检查它是否满足您的时间限制吗?@kavish看到我的答案了吗。我已经实现了几乎完全相同的算法(没有霍布斯提出的优化),但它在
n=1000000
..@Blender中立即运行,非常…:-(遗憾的是,他太固执了……但你知道,我必须提高自己的声誉,因为我没有太多的时间,所以,我会有一个忙碌的星期……@Blender:不,实际上这不是我的家庭作业。我在网上遇到了一些很好的组合问题,我被困在其中一类问题中。@kavish,我的答案有什么问题吗,最后我的答案是ma你不接受吗?@kavish,这与任何其他建议有什么不同?@H2CO3:你的回答我接受了。我只是站在这个方法的反面,因为我认为,如果有这么多好的m prime算法,那么也会有好的m not prime算法。@Blender…:-(遗憾的是,他太固执了……但你知道,我必须提高自己的声誉,因为我没有太多的时间,所以,我会有一个忙碌的星期……@Blender:不,实际上这不是我的家庭作业。我在网上遇到了一些很好的组合问题,我被困在其中一类问题中。@kavish,我的答案有什么问题吗,最后我的答案是ma你不接受吗?@kavish,这与任何其他建议有什么不同?@H2CO3:你的回答我接受了。我只是站在这个方法的反面,因为我认为如果有这么多好的m prime算法,那么m not prime也会有好的算法。