Timus 1110. Power 要求计算乘方(取模)问题。
1110. Power
Time Limit: 0.5 second
Memory Limit: 16 MB
Memory Limit: 16 MB
You are given the whole numbers N, M and Y. Write a program that will find all whole numbers X in the interval [0, M−1] such that XN mod M = Y.
Input
The input contains a single line with N, M and Y (0 < N < 999, 1 < M < 999, 0 < Y < 99) separated with one space.
Output
Output all numbers X separated with space on one line. The numbers must be written in ascending order. If no such numbers exist then output −1.
Sample
input | output |
---|---|
2 6 4 |
2 4 |
Problem Source: Bulgarian National Olympiad Day #1
解答如下:
1 using System;
2
3 namespace Skyiv.Ben.Timus
4 {
5 // http://acm.timus.ru/problem.aspx?space=1&num=1110
6 sealed class T1110
7 {
8 static void Main()
9 {
10 string[] ss = Console.ReadLine().Split();
11 int n = int.Parse(ss[0]);
12 int m = int.Parse(ss[1]);
13 int y = int.Parse(ss[2]);
14 bool ok = false;
15 for (int x = 0; x < m; x++)
16 {
17 if (ModPow(x, n, m) == y)
18 {
19 ok = true;
20 Console.Write(x + " ");
21 }
22 }
23 if (!ok) Console.Write(-1);
24 }
25
26 static int ModPow(int x, int n, int m)
27 {
28 int z = 1;
29 for (int i = 0; i < n; i++) z = (z * x) % m;
30 return z;
31 }
32 }
33 }
34
2
3 namespace Skyiv.Ben.Timus
4 {
5 // http://acm.timus.ru/problem.aspx?space=1&num=1110
6 sealed class T1110
7 {
8 static void Main()
9 {
10 string[] ss = Console.ReadLine().Split();
11 int n = int.Parse(ss[0]);
12 int m = int.Parse(ss[1]);
13 int y = int.Parse(ss[2]);
14 bool ok = false;
15 for (int x = 0; x < m; x++)
16 {
17 if (ModPow(x, n, m) == y)
18 {
19 ok = true;
20 Console.Write(x + " ");
21 }
22 }
23 if (!ok) Console.Write(-1);
24 }
25
26 static int ModPow(int x, int n, int m)
27 {
28 int z = 1;
29 for (int i = 0; i < n; i++) z = (z * x) % m;
30 return z;
31 }
32 }
33 }
34
这里关键是 ModPow 方法。如果是 Pow 方法,以下实现比较高效:
1 static int Pow(int x, int n)
2 {
3 int z = 1;
4 for (int p = x; n > 0; n >>= 1, p *= p) if ((n & 1) != 0) z *= p;
5 return z;
6 }
7
2 {
3 int z = 1;
4 for (int p = x; n > 0; n >>= 1, p *= p) if ((n & 1) != 0) z *= p;
5 return z;
6 }
7
不过,Pow 方法很容易溢出,更适用于 x 和 z 是 BigInteger 的情形。
根据3楼 guest 朋友的评论,可以将程序中第 26 到 31 行的 ModPow 方法改为以下更高效的代码:
static int ModPow(int x, int n, int m)
{
int z = 1;
for (int p = x; n > 0; n >>= 1, p = (p * p) % m) if ((n & 1) != 0) z = (z * p) % m;
return z;
}
{
int z = 1;
for (int p = x; n > 0; n >>= 1, p = (p * p) % m) if ((n & 1) != 0) z = (z * p) % m;
return z;
}
经测试,运行时间从原来的 0.14 秒降低到 0.125 秒。