一个100k位数的模数

时间:2014-02-18 17:01:17

标签: c modulus

对于数字nm,我需要评估n % m

捕获量n可以与10^100000一样大,m最大值10^18

unsigned long long约为2^64(如果我错了请纠正我),这是不行的, 然后我想我可以用字符数组来读它,但是如何计算字符的剩余部分。

有没有办法将这个数字减少到一个较小的数字,以便它可以从char数组转移到unsigned long long(如atol但是long long而不是long )。

此外,我认为我需要更快的方式来做%,因为时间限制为0.1秒

感谢任何帮助。

3 个答案:

答案 0 :(得分:13)

您可以使用许多技巧来简化模块化算术。例如,假设您想知道1234567890 mod 17是什么,但是您没有足够大的数字类型来表示1234567890.那么,我们对%有什么了解,假设所有数字都是正数?

(a+b)%e == ((a%e)+(b%e))%e
(c*d)%e == ((c%e)*(d%e))%e

如果您不理解为什么这些身份属实,请回到%的定义并研究它们,直到您拥有 solid

现在我们知道了,我们知道

1234567890 % 17 = (12345 * 100000 + 67890) % 17
                = ((((12345 % 17) * (100000 % 17)) % 17) + (67890 % 17)) % 17

现在你的数字只有很少。如果这些数字仍然太大,请继续将它们分解,直到它们足够小。

我在Math StackExchange网站上回答了一个非常类似的问题;它也可能对你有帮助。

https://math.stackexchange.com/questions/91583/implementing-fermats-primality-test/91584#91584

答案 1 :(得分:1)

或者,也可以复制二年级学生在数学课上做的事情来计算结果和分数的剩余部分:

  • 尝试从左侧划分第一个数字
  • 将结果放在右下方(对我们的事业不重要)
  • 计算该数字的余数
  • 将下一个数字放在上一个剩余部分旁边

...基本上每次将余数乘以10并加上后续数字,直到我们用尽所有数字。如何存储用户从标准输入输入的数字取决于您,这应该是它。这是一个例子:

#include <stdio.h>

int main( ){
    unsigned long long number[100000] = { 0 };
    int length = 0;
    unsigned long long divident = 0;
    char temp = 0;

    puts( "first-operand % second-operand\n" );

first:

    printf( "first-operand: " );
    temp = getchar( );
    while ( temp != 10 ){
        if ( temp <= '9' && temp >= '0' && length < 100000 ) {
            number[length] = temp - '0';
            length++;
        }
        else {
            while ( length ) {
                length--;
                number[length] = 0;
            }
            fflush( stdin );
            puts( "Invalid input, again from the beginning..." );
            goto first;
        }
        temp = getchar( );
    }


second:

    printf( "second-operand: " );
    temp = getchar( );
    while ( temp != 10 ){
        if ( temp <= '9' && temp >= '0' ) divident = divident * 10 + temp - '0';
        else {
            divident = 0;
            fflush( stdin );
            puts( "Invalid input, again from the beginning..." );
            goto second;
        }
        temp = getchar( );
    }

    puts( "The result is..." );

    length--;
    for ( long i = 0; i < length; i++ ) {
        number[i + 1] += 10 * number[i] % divident;
    }
    printf( "%lli", number[length] % divident );

    fflush( stdin );
    getchar( );

    return 0;
}

我无法真正测试它的大数字,因为我可能不确定答案,或者有时间写下10万个数字...对不起这个问题的答案很晚,我被说服做其他事情

答案 2 :(得分:1)

读取n的所有数字作为字符,并读取m长 算法:
1. if(strlen(n)&lt; strlen(m))printf(“%s”,n);
2.否则:如果有,请获取前17位数字(在这种情况下17为最长数字)并使用函数 strtoull 将它们转换为long long,例如:number = strtoull(digits, tmp,10)
3.做计算:tmp_rest =数字%m
4.使用 sprintf 函数将tmp_rest转换为字符串,例如。 sprintf(string_digits,“%lld”,tmp_rest)
5.使用string_digits从第17位开始替换前17位数字并向左移动 6.从2.重复,但以17-strlen(string_digits)作为起始点再获得17位数。重复,直到有足够的数字(&gt; = 17) 7.对于其余数字(0&lt; strlen(数字)&lt; 17) - &gt;执行2.和3.解决方案是tmp_rest;)

请参阅:http://bytes.com/topic/software-development/insights/793965-how-find-modulus-very-large-number