📜  算法测验| SP2竞赛1 |问题23(1)

📅  最后修改于: 2023-12-03 15:11:33.188000             🧑  作者: Mango

算法测验 | SP2竞赛1 | 问题23

这是一个涉及到数论和字符串操作的竞赛题目,需要熟练掌握大数和模运算相关算法。

题目描述

给定两个正整数 $a$ 和 $b$,计算 $a^b$ 对 $10^{100}$ 取模后的结果。

输入格式

两个正整数 $a$ 和 $b$,$1 \leq a, b \leq 10^{100}$。

输出格式

一个字符串,即 $a^b$ 对 $10^{100}$ 取模后的结果。

输入样例
2 5
输出样例
0000000000000000000000000000000000000000000000000000000000000000032
解题思路

首先需要注意到输入的两个数所代表的值的大小,无法使用标准的 int 或者 long 数据类型进行计算,因此需要使用字符串来表示。但是在进行模运算时,我们需要使用大数模板中封装了取模的操作来进行。

具体来说,我们可以使用快速幂算法来计算 $a^b$,在计算每一步的乘积时使用大数模板中提供的取模操作进行处理。需要注意的是,我们在计算幂时使用的是矩阵快速幂,相较于直接循环计算幂,这种方法可以更快地得出幂的结果。

关键代码

使用 python 语言中的大数模板库来进行大数操作和取模:

# 大数模板
class BigNumber(str):
    def __init__(self, x = 0):
        if isinstance(x, str):
            super().__init__()
        else:
            super().__init__(str(x))
    def __str__(self):
        return super().__str__()
    def __int__(self):
        return int(str(self))
    def __repr__(self):
        return self.__str__()

def mod(a: BigNumber, b: BigNumber) -> BigNumber:
    r = 0
    for c in str(a):
        r *= 10
        r += int(c)
        r %= int(b)
    return BigNumber(r)

在计算过程中,需要使用矩阵快速幂来较快地得出幂的结果。这里,我们封装了一个矩阵类,方便进行矩阵乘法计算:

# 矩阵类
class Matrix:
    def __init__(self, data):
        self.data = data
    def __mul__(self, other):
        if isinstance(other, Matrix):
            res = [[0 for j in range(len(other.data[0]))] for i in range(len(self.data))]
            for i in range(len(self.data)):
                for j in range(len(other.data[0])):
                    for k in range(len(other.data)):
                        res[i][j] += self.data[i][k] * other.data[k][j]
            return Matrix(res)
        else:
            return Matrix([i * other for i in self.data])
    def __repr__(self):
        s = ''
        for i in range(len(self.data)):
            s += '[%s]\n' % ' '.join(str(j) for j in self.data[i])
        return s.strip()

使用快速幂计算矩阵 A 的 B 次幂,并将每一步结果取模再进行下一步计算:

# 快速幂计算
def powMod(A: Matrix, B: BigNumber, mod: BigNumber) -> Matrix:
    res = Matrix([[(i == j) and 1 or 0 for j in range(len(A.data))] for i in range(len(A.data))])
    while B != BigNumber(0):
        if mod(B, 2) == BigNumber(1):
            res = res * A
        A = A * A
        B = BigNumber(int(B) // 2)
    for i in range(len(res.data)):
        for j in range(len(res.data[i])):
            res.data[i][j] = mod(BigNumber(res.data[i][j]), mod)
    return res
完整代码
# -*- coding: utf-8 -*-

# 大数模板
class BigNumber(str):
    def __init__(self, x = 0):
        if isinstance(x, str):
            super().__init__()
        else:
            super().__init__(str(x))
    def __str__(self):
        return super().__str__()
    def __int__(self):
        return int(str(self))
    def __repr__(self):
        return self.__str__()

def mod(a: BigNumber, b: BigNumber) -> BigNumber:
    r = 0
    for c in str(a):
        r *= 10
        r += int(c)
        r %= int(b)
    return BigNumber(r)

# 矩阵类
class Matrix:
    def __init__(self, data):
        self.data = data
    def __mul__(self, other):
        if isinstance(other, Matrix):
            res = [[0 for j in range(len(other.data[0]))] for i in range(len(self.data))]
            for i in range(len(self.data)):
                for j in range(len(other.data[0])):
                    for k in range(len(other.data)):
                        res[i][j] += self.data[i][k] * other.data[k][j]
            return Matrix(res)
        else:
            return Matrix([i * other for i in self.data])
    def __repr__(self):
        s = ''
        for i in range(len(self.data)):
            s += '[%s]\n' % ' '.join(str(j) for j in self.data[i])
        return s.strip()

# 快速幂计算
def powMod(A: Matrix, B: BigNumber, mod: BigNumber) -> Matrix:
    res = Matrix([[(i == j) and 1 or 0 for j in range(len(A.data))] for i in range(len(A.data))])
    while B != BigNumber(0):
        if mod(B, 2) == BigNumber(1):
            res = res * A
        A = A * A
        B = BigNumber(int(B) // 2)
    for i in range(len(res.data)):
        for j in range(len(res.data[i])):
            res.data[i][j] = mod(BigNumber(res.data[i][j]), mod)
    return res

a, b = input().split()

# 构造矩阵
A = Matrix([[0, 1], [1, 1]])

# 转化大数
a = BigNumber(a)
b = BigNumber(b)

# 矩阵快速幂
res = powMod(A, b, BigNumber(10) ** 100)

# 取模输出
print(str(res.data[0][1]).zfill(100))