题目链接

好多次方 (质数模)

题目描述

给定三个正整数 ,请计算以下表达式的值:

解题思路

本题要求计算一个嵌套指数对一个固定的 质数 取模的结果。当模数 是质数时,我们可以使用 费马小定理 来简化指数,这比扩展欧拉定理更为直接。

  1. 费马小定理

    该定理指出,如果 是一个质数,而整数 不是 的倍数(即 ),则有:

    这个性质意味着指数是以 为周期的。对于任意正整数指数 ,我们可以将指数对 取模来降幂。

  2. 指数降幂的陷阱与修正

    直接使用 作为新指数存在一个问题:当 恰好是 的倍数时,。这会导致最终计算

    • 如果 ,这个结果是正确的,因为
    • 但如果 ,正确结果应该是 ,而 则是错误的。

    为了解决这个问题,我们需要确保当指数是 的正倍数时,它被映射到 而不是 。一个严谨的降幂法则是:

    这个公式对所有 都成立。

  3. 算法流程

    令模数

    • 步骤 1:计算指数 我们需要计算 的指数,但只需要它对 取模的结果。 使用快速幂计算 。但为了应用修正后的公式,我们实际计算的是 。 这等价于先计算 的值,再进行模运算。由于 会非常大,我们不能直接计算。

      正确的做法是计算

      • 如果 不为 ,它就是我们想要的指数。
      • 如果 ,说明 的倍数,此时我们应该使用 作为指数。
    • 步骤 2:计算最终结果 得到简化后的指数 后,再用一次快速幂计算最终结果。

代码

#include <iostream>

using namespace std;

const int MOD = 1e9 + 7;

long long power(long long base, long long exp, long long mod) {
    long long res = 1;
    base %= mod;
    while (exp > 0) {
        if (exp % 2 == 1) {
            res = (res * base) % mod;
        }
        base = (base * base) % mod;
        exp /= 2;
    }
    return res;
}

void solve() {
    long long a, b, c;
    cin >> a >> b >> c;
    
    long long exp = power(b, c, MOD - 1);
    if (exp == 0) {
        exp = MOD - 1;
    }
    
    cout << power(a, exp, MOD) << endl;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}
import java.util.Scanner;

public class Main {
    private static final int MOD = 1_000_000_007;

    private static long power(long base, long exp, long mod) {
        long res = 1;
        base %= mod;
        while (exp > 0) {
            if (exp % 2 == 1) {
                res = (res * base) % mod;
            }
            base = (base * base) % mod;
            exp /= 2;
        }
        return res;
    }

    private static void solve(Scanner sc) {
        long a = sc.nextLong();
        long b = sc.nextLong();
        long c = sc.nextLong();
        
        long exp = power(b, c, MOD - 1);
        if (exp == 0) {
            exp = MOD - 1;
        }
        
        System.out.println(power(a, exp, MOD));
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while (T-- > 0) {
            solve(sc);
        }
    }
}
MOD = 10**9 + 7

def power(base, exp, mod):
    res = 1
    base %= mod
    while exp > 0:
        if exp % 2 == 1:
            res = (res * base) % mod
        base = (base * base) % mod
        exp //= 2
    return res

def solve():
    a, b, c = map(int, input().split())

    exp = power(b, c, MOD - 1)
    if exp == 0:
        exp = MOD - 1

    print(power(a, exp, MOD))

def main():
    try:
        T = int(input())
        for _ in range(T):
            solve()
    except (IOError, ValueError):
        pass

if __name__ == "__main__":
    main()

算法及复杂度

  • 算法:数论、费马小定理、快速幂
  • 时间复杂度:对于每个测试用例,需要进行两次快速幂运算。第一次计算指数,复杂度为 ;第二次计算最终结果,复杂度为 。因此,每个测试用例的总时间复杂度为 组测试用例的总复杂度为
  • 空间复杂度:算法仅使用有限的几个变量,因此空间复杂度为