題目

  • Time limit: 1.00 s
  • Memory limit: 512 MB

Your task is to efficiently calculate values aba^b modulo 109+710^9+7.
Note that in this task we assume that 00=10^0=1.

Input Output
The first input line contains an integer nn: the number of calculations.
After this, there are nn lines, each containing two integers aa and bb.
Print each value aba^b modulo 109+710^9+7.

Constraints

  • 1n21051 \le n \le 2 \cdot 10^5
  • 0a,b1090 \le a,b \le 10^9

Example:

Input Output
3
3 4
2 8
123 123
81
256
921450052

解法

快速冪

理論

要快速計算乘方,這題顯然就是快速冪。
我們以一個例子解釋快速冪的邏輯。假設我們要計算a32a^32,我們其實不需要真的將aa3232次乘法,而可以依序計算a2a^2a4=(a2)2a^4=(a^2)^2a8=(a4)2a^8=(a^4)^2a16=(a8)2a^{16}=(a^8)^2a32=(a16)2a^{32}=(a^{16})^2。這樣可以讓指數的大小本身亦以指數增長,進而讓ana^n的時間複雜度從O(n)O(n)降到O(logn)O(\log n)

對於一般(非22的次冪)的指數nn,快速冪的邏輯如下:
欲計算ana^n,先將nn以二進位表示(這麼做是為了用指數律將ana^n拆成若干個akia^{k_i}相乘,其中每個次方kik_i都是22的冪次,而由上我們可知22的冪次很好算)。舉例來說,若n=1310=11012n=13_{10}=1101_2,則an=a13=a8a4a1a^n=a^{13}=a^8a^4a^1。接下來便是照我們上面說的一次把a8,a4,a1a^8, a^4, a^1都算出來,再相乘即可。

但其實實務上我們不是這樣做的,實務上做法是:
如果指數是偶數(設n=2kn=2k),那麼an=(a2)ka^n=(a^2)^k
如果指數是奇數(設n=2k+1n=2k+1),則把ana^n拆成aa2k=a(a2)kaa^{2k}=a(a^2)^k
如此我們每經一次操作,指數都會變成約原先的一半。

處理模數

題目額外要求了要將答案模109+710^9+7,就是因為計算過程中出現的數字和答案可能太大。但這不困難,只要將上述快速冪中每個乘法步驟都取模即可。

C++ Code

綜合以上,我們有快速冪的程式如下:

#define ll long long
ll fast_pow(ll base, ll exp, int m){
  ll res = 1LL;
  while(exp > 0){
    if(exp%2==1){res = (res*base) % m;}
    base = (base*base) % m;
    exp /= 2;
  }
  return res;
}

AC Code

此題的完整程式碼如下:

#include<bits/stdc++.h>
using namespace std;

const int M = (int)1e9 + 7;
#define ll long long

ll fast_pow(ll base, ll exp, int m){
  ll res = 1LL;
  while(exp > 0){
    if(exp%2==1){res = (res*base) % m;}
    base = (base*base) % m;
    exp /= 2;
  }
  return res;
}
int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  ll n, a, b;
  cin >> n;
  while(n--){
    cin >> a >> b;
    cout << fast_pow(a,b,M) << "\n";
  }
}