Time Limit: 2 Seconds Memory Limit: 65536 KB
Give a number n, find the minimum x that satisfies 2^x mod n = 1.
Input
One positive integer on each line, the value of n.
Output
If the minimum x exists, print a line with 2^x mod n = 1.
Print 2^? mod n = 1 otherwise.
You should replace x and n with specific numbers.
Sample Input
2
5
Sample Output
2^? mod 2 = 1
2^4 mod 5 = 1
Author: MA, Xiao
Source: ZOJ Monthly, February 2003
这道题看起来描述是够少的,我就喜欢这种题目,本人英文不是很好。。。。
题目非常清晰,就是要求2的X次方除以N的余数为1时的X的值。刚看到这道题目的时候,我不假思索的就认为,这种题目通过表驱动的方式是一个很好的办法,于是我就想着先打一张2的32次方的表格,然后每次求结果的时候只要遍历这张表就可以了,于是就有了下述代码:
#include<iostream>
using namespace std;
const int NUM = 32;
int *pow2 = new int[NUM];
void initial2Pow()
{
*pow2 = 1;
for(int i = 1; i < NUM; i++)
*(pow2 + i) = 2*(*(pow2 + i - 1));
}
int main()
{
initial2Pow();
int n;
while(cin>>n)
{
if(n%2 == 0 || n < 2)
{
cout<<"2^? mod "<<n<<" = 1"<<endl;
continue;
}
bool find = false;
for(int i = 1;i < NUM;i++)
{
if((*(pow2 + i))%n == 1)
{
cout<<"2^"<<i<<" mod "<<n<<" = 1"<<endl;
find = true;
break;
}
}
if(!find)
{
cout<<"2^? mod "<<n<<" = 1"<<endl;
}
}
}
感觉代码比较简练,可以提交了,但是已提交却得到了WA!这时,我意识到可能是由于精度问题,int 的32位可能不够,于是我用64 位 long long 来代替int,重新提交之后,仍然得到WA !这时我发现,这题其实还是不是那么简单的!至少不应该仅仅是简单的表驱动来解决这个问题。还是需要一些数学技巧的。首先我把计算过程用笔写在了之上:
a / b = c …………..d,此时等式两边乘以2,得到2a / b = 2c ……. 2d, 此时发现,2a % b得到的余数,与2d%b的余数是一样的!
若2d / b = c0…..d0, 则有2a / b = 2c + c0 …….d0, 有了这些数学的推论后,修正代码如下:
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n%2 == 0 || n < 2)
{
cout<<"2^? mod "<<n<<" = 1"<<endl;
continue;
}
bool find = false;
int d = 1;
for(int i = 1;;i++)
{
d *= 2;
if(d%n == 1)
{
cout<<"2^"<<i<<" mod "<<n<<" = 1"<<endl;
find = true;
break;
}
d = d%n;
}
if(!find)
{
cout<<"2^? mod "<<n<<" = 1"<<endl;
}
}
}成功AC !