Problem
Professor Shekhu has another problem for Akki today. He has given him three positive integers A, N and P and wants him to calculate the remainder when AN! is divided by P. As usual, N! denotes the product of the first N positive integers.
Input
The first line of the input gives the number of test cases, T. T lines follow. Each line contains three integers A, N and P, as described above.
Output
For each test case, output one line containing Case #x: y
, where x
is the test case number (starting from 1) and y
is the answer.
Limits
1 ≤ T ≤ 100.
Small dataset
1 ≤ A ≤ 10.
1 ≤ N ≤ 10.
1 ≤ P ≤ 10.
Large dataset
1 ≤ A ≤ 105.
1 ≤ N ≤ 105.
1 ≤ P ≤ 105.
Sample
In Sample Case #1, the answer is the remainder when 21! = 2 is divided by 2, which is 0.
In Sample Case #2, the answer is the remainder when 33! = 36 = 729 is divided by 2, which is 1.
这一题需要注意的是,比如说 2^(4!),是 2^24,而不是 2^4 * 2^3 * 2^2 * 2^1=2^10.
对于数量级比较小的数,直接用直观的方法就好了:
Small dataset
对于数量级小的数,先计算 N! . 之后再计算 An mod P。注意,这里用到了一点:取模运算满足分配律 (a * b) % p = (a % p * b % p) % p
ans = 1
for i = 1 to factorial(N)
ans = (ans * A) % P
return ans
因为
P
和
A
都不大于 10
5
, 而且我们在每一阶都取模了,所以我们不用担心
(ans *
A
) 会溢出。
public int solve(int A, int N, int P){
int ans = 1;
int n=factorial(N);
for (int i = 1; i <= n; i++) {
ans = (ans * A) % P;
};
return ans;
}
public int factorial(int N){
if(N==1){
return 1;
}
return N*factorial(N-1);
}
Large dataset
起初,似乎这个问题需要一个数论的方法。 但是确实存在一个非常简单的解决方案,主要是使用快速求幂的方法。
首先,对于一个给定的 n ,先计算 An mod P . 我们可以使用分而治之的方法来得到一个 O(log n) 的解决方案:
An mod P = ( A^(n/2) mod P * A^(n/2) mod P ) mod p
pow(a, n, p):
if n == 0
return 1
pow_half = pow(a, n / 2, p)
pow_half_sq = (pow_half * pow_half) % p
if n % 2 == 0
return pow_half_sq
else //n是奇数时,n/2取整时则少了一次乘法,所以要补上
return (pow_half_sq * a) % p
之后我们再利用: ab*c = abc. 所以 AN! = A123.... 另外,因为取模运算满足结合律,所以我们可以在任何时候对 ans 进行取模操作。所以,下面是时间复杂度为 O(N log N) 的解决方案:
ans = A % P
for i = 2 to N
ans = pow(ans, i, P)
return ans
具体代码如下:(注意要用 long,用 int 会答案错误,因为有中间值会溢出)
public long solve(int A, int N, int P) {
long yushu = A % P;
for (int i = 2; i <= N; i++) {
yushu = helper2(yushu, i, P);
}
System.out.println(yushu);
return yushu;
}
// 计算(A^N)%P
public long helper2(long A, int N, int P) {
if (A == 0 || A == 1) {
return A % P;
}
if (N == 0) {
return 1 % P;
}
long half = helper2(A, N / 2, P);
long ans = (half * half) % P;
if (N % 2 == 0) {
return ans;
} else {
return (ans * A) % P;
}
}
附上这道题的地址:
https://codejam.withgoogle.com/codejam/contest/dashboard?c=3254486#s=p0&a=0