14

我正在尝试解决编程竞赛的初步问题,其中 2 个问题我必须计算和打印一些非常大的整数(如 100!、2^100)。

我还需要一种快速的方法来计算这个大整数的幂。

你能给我一些算法或数据结构的建议吗?(顺便说一句,我读过 C 接口和实现的“任意精度算术”部分,但它对 pow() 没有帮助)

编辑:我认为通过平方方法和位移的幂运算可以提高功率,但我还需要一种快速的方法来计算这个整数的阶乘。谢谢。

EDIT2:对于那些有兴趣的人;

找到包含长度为 N 的所有位串的最短位串长度(对不起我的英语,我会举个例子)。N <= 10000

例如,包含所有长度为 2(00, 01, 10, 11) 的位串的最短位串长度是 5(11001)。

我对这个问题的解决方案是 2^n + n - 1。(所以我应该计算 2 的幂,我想我会使用位移)

另一个问题是,给定 2 个长度,找出有多少种不同的方式可以达到长度 N。例如,输入是 10、2、3。那么你应该用 2 和 3 达到 10(例如,2+ 2+2+2+2、2+2+3+3、3+2+2+3、3+3+2+2...)。1 <= N < 2^63。我们将在 mod 1000000007 中计算 anwser。

我的解决方案是 2x + 3y = N,所以 x = (N - 3y) / 2 。对于从 0 到 2*N / 3 的 y,如果 x 是整数,那么我应该计算这个 X 和 Y 的广义排列,总计 += (x+y)!/ (x!*y!)。

4

7 回答 7

6

对于pow整数,通过平方取幂

于 2011-04-04T21:08:45.287 回答
1

你可能想看看加密程序的实现(尤其是我首先想到的 GnuPG)。原因是加密函数也使用非常大的整数(所谓的 MultiPrecision Integers - MPI)。这些 MPI 的存储方式是,前 2 个字节告诉整数的大小,后面的字节如何存储值。

GPG 是开源的,请看一下 :)

于 2011-04-04T21:36:46.100 回答
1

要计算幂,请使用二分法算法,该算法使用指数的二进制表示并减少乘法的结果数量。数据结构只是一个整数数组

于 2011-04-04T21:06:47.780 回答
1

使用GMP来处理这些。它内置了阶乘支持和强大的功能等。它具有 C 和 C++ 接口等。您将需要mpz_t一个包含非常大整数的类型。

于 2011-04-05T07:56:03.147 回答
0

基础数学可以做任何双倍与双倍的乘法...

def biginteger(num1, num2):
result = []
lnum1 = len(num1)
lnum2 = len(num2)

k = x = remainder = 0
while len(result) < lnum1:
    result.append(0)
for i in range(lnum1, 0, -1):
    multiplier = int(num1[i - 1])
    for j in range(lnum2, 0, -1):
        temp = (int(num2[j - 1]) * multiplier) + remainder + int(result[k])
        result[k] = str(temp % 10)
        remainder = temp / 10
        k += 1
    result.append(str(remainder))
    if remainder != 0:
        remainder = 0
    x += 1
    k = x

return ''.join([result[i - 1] for i in range(len(result), 0, -1)])

num1 = '37234234234234'
num2 = '43234234234232'
print biginteger(num1, num2)
于 2012-04-06T18:31:51.513 回答
0

您可以按以下格式存储数字:该数字的位数和数字数组。这是在编程竞赛中处理大量数字的常用方法。

这是一个提供数字和乘法存储的类。可以添加数字的输入和输出,这是微不足道的。

class huge {
public:
    int size;
    int data[1000];

    friend void mul(const huge &a, int k, huge &c) {
        c.size = a.size;
        int r = 0;
        for (int i = 0; i < a.size; i++) {
            r += a.data[i] * k;
            c.data[i] = r % 10;
            r = r / 10;
        }
        if (r > 0) {
            c.size++;
            c.data[c.size - 1] = r;
        }
        while (c.size > 1 && c.data[c.size - 1] == 0)
            c.size--;
    }

    friend void mul(const huge &a, const huge &b, huge &c) {
        c.size = a.size + b.size;
        memset(c.data, 0, c.size * sizeof(c.data[0]));
        for (int i = 0; i < a.size; i++) {
            int r = 0;
            for (int j = 0; j < b.size; j++) {
                r += a.data[i] * b.data[j] + c.data[i + j];
                c.data[i + j] = r % 10;
                r /= 10;
            }
            if (r > 0)
                c.data[i + b.size] = r;
        }
        while (c.size > 1 && c.data[c.size - 1] == 0)
            c.size--;
    }
};
于 2011-04-04T21:44:52.597 回答
0

对于 C 来说,这样的东西可以工作,或者使用 int 或 char 数组自己滚动,数组中的一个点代表一个数字。 [1 | 0 | 1]['1'|'0'|'1']101 等。

于 2011-04-04T21:04:34.067 回答