找到2 ^ n的最后10位数

时间:2018-01-14 10:46:55

标签: c unsigned-long-long-int

所以我应该找出2 ^ n的最后10位数(0 <= n <= 100),其中n是输入。我找到了一种处理大数字的方法,但是当n> 64时程序失败了。任何关于如何解决这个问题的线索都将不胜感激。

#include<stdio.h>
#include<math.h>


/* Iterative Function to calculate (x^y)%p in O(log y) */
int power(long long int x, long long int y, long long int p)
{
long long int res = 1; // Initialize result

x = x % p; // Update x if it is more than or
// equal to p

while (y > 0) {

    // If y is odd, multiply x with result
    if (y & 1)
        res = (res * x) % p;

    // y must be even now
    y = y >> 1; // y = y/2
    x = (x * x) % p;
}
return res;
}

// C function to print last 10 digits of a^b
void printLastDigits(long long int a,long long int b)
{    

long long int temp = pow(10,10);

// Calling modular exponentiation
temp = power(a, b, temp);

if (temp)
    printf("%d",temp);
}

int main()
{
long long int n;
scanf("%d",&n);
printLastDigits(2,n);
return 0;
}

4 个答案:

答案 0 :(得分:1)

您不需要担心“高”&#39;比特,因为乘以2 左移它们超出了您感兴趣的产品下部的范围。请确保您正在使用{{ 1}}类型(至少64位)用于保存足够宽的整数类型,例如

unsigned long long

您可以使用bignum计算器测试#include <inttypes.h> #include <stdio.h> void low_digits (unsigned int n) { unsigned long long base = 2, modulus = 10000000000ULL; for (unsigned int i = 1; i <= n; i++) { fprintf(stdout, "2^%u mod 10^10 = %llu\n", i, base); base = (base * 2) % modulus; } }

10715086071862673209484250490600018105614048117055336074437503883703 \ 51051124936122493198378815695858127594672917553146825187145285692314 \ 04359845775746985748039345677748242309854210746050623711418779541821 \ 53046474983581941267398767559165543946077062914571196477686542167660 \ 429831652624386837205668069376

而上面的2^1000收益率为:5668069376

其他人已经注意到,这是一种n = 1000方法,对于足够大的naive值,模幂运算效率更高。不幸的是,这将需要超出无符号64位值范围的产品,因此,除非您准备实施(n)多精度mul / mod操作,否则它可能超出你的任务范围。

幸运的是,更高版本的gcc和clang确实提供了扩展的128位整数类型:

[hi64][lo64]

答案 1 :(得分:1)

以下使用字符串执行乘法运算:

void lastdigits(char digits[11], int n)
{
    int i, j, x, carry;
    for (i=0; i<n;i++) {
        for (j=9, carry=0; j>=0; j--) {
            x= digits[j]-'0';
            x *= 2;
            x += carry;
            if (x>9) {carry= 1; x -= 10;}
            else carry= 0;
            digits[j]= x+'0';
        }
    }
}

void test(void)
{
    char digits[11];

    strcpy(digits,"0000000001");
    lastdigits(digits,10);
    printf("%s\n",digits);

    strcpy(digits,"0000000001");
    lastdigits(digits,20);
    printf("%s\n",digits);

    strcpy(digits,"0000000001");
    lastdigits(digits,100);
    printf("%s\n",digits);
}

输出:

0000001024
0001048576
6703205376

答案 2 :(得分:1)

由于你收到的其他答案实际上没有表明你做错了什么:

x = (x * x) % p;

您认为x * x仍然适合long long int。但如果x0x100000000(4294967296,10位十进制数)且long long int为64位,则不适合。

或者:

您需要一种方法来准确地将两个任意10位数字相乘。结果可能包含20位数字,可能不适合long long int甚至unsigned long long int。这意味着你需要使用一些bigint库或者自己实现类似的东西。

或者:

您需要避免乘以多个可能的10位数字。

您接受的答案选择2进行简单的重复乘法。这对于您现在的问题已经足够了,但请注意,如果您想允许非常大的指数,这会显着增加复杂性。

答案 3 :(得分:1)

让我们说你找到2 ^ n的最后一个数字,你只需要考虑最后一位数并忽略所有其他数字

1. 2*2 = 4
2. 4*2 = 8
3. 8*2 = 16 (ignore last-but-one digit i.e 1)
4. 6*2 = 12 (ignore last-but-one digit i.e 1)
5. 2*2 = 4
6. 4*2 = 8
7. 8*2 = 16 (ignore last-but-one digit i.e 1)
8. 6*2 = 12 (ignore last-but-one digit i.e 1)
9. 2*2 = 4

... n-1 iterations

要查找2 ^ n的最后2位数,请忽略除最后2位数之外的所有数字。

1. 2*2 = 4
2. 4*2 = 8
3. 8*2 = 16
4. 16*2 = 32
5. 32*2 = 64
6. 64*2 = 128 (Consider last 2 digits)
7. 28*2 = 56
8. 56*2 = 112 (Consider last 2 digits)
9. 12*2 = 24

... n-1 iterations

同样,要查找2 ^ n的最后10位数,请在每次迭代时考虑最后10位数,并重复n-1次迭代。

注意:

使用这种方法,你在计算过程中获得的最大数字可以是11位~10 ^ 11,而对于64位机器,最大值是~2 ^ 64 = ~10 ^ 18 < / p>