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 秒。