hdu 1395 2^x(mod n) = 1
题目描述
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
Give a number n, find the minimum x(x>0) that satisfies .
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
中文翻译
Problem Description
给出一个数字n,找到满足的最小x(x> 0)。
Input
每行一个正整数,n的值。
Output
如果存在最小x,则打印一条2^x mod n = 1的行。
否则,打印2^?mod n = 1。
您应该用特定数字替换x和n。
Sample Input
2
5
Sample Output
2^? mod 2 = 1
2^4 mod 5 = 1
解题思路
先贴出欧拉定理:
若n,a为正整数,且n,a互质,则
-
当n=1时,明显不成立,所以找不到最小的x。
-
当n为偶数时,是偶数,一个偶数模另外一个偶数,明显也不成立,所以找不到最小的x。
-
当n为非1的奇数时,n和2互质,由欧拉定理,令a=2,n为输入的奇数,则根据欧拉函数计算得φ(n),代入欧拉定理得,即。
对比题目要求的,很容易发现φ(n)必是符合要求的x。
但φ(n)未必是最小的x,所以就可以从1~φ(n)遍历,找到符合题目 最小的x。
注意:计算2^x mod n时用快速幂乘,否则不但慢还容易爆。
问题解答
#include <iostream>
#define LL long long
using namespace std;
int oula(int n)//计算n的欧拉函数
{
int rea=n;
for(int i=2; i*i<=n; i++)
if(n%i==0)//第一次找到的必为素因子
{
rea=rea-rea/i;
do
n/=i;//把该素因子全部约掉
while(n%i==0);
}
if(n>1)
rea=rea-rea/n;
return rea;
}
LL ksm(LL a,LL b,LL mod)//快速幂计算2^b%mod
{
LL ans = 1;
a %= mod;
while( b>0 )
{
if( b&1 ) ans = (ans*2)%mod;
b >>= 1;//位运算,右移1位,相当于除以2
a = (a*a)%mod;
}
return ans;
}
int main()
{
ios::sync_with_stdio(0);
int n,x;
bool flag;
while( cin>>n )
{
flag = 0;
if( (n&1) && (n!=1) )//当n为非1的奇数时
{
flag = 1;
int phi = oula(n);
cout << phi << endl;
for(x=1;x<phi;++x)
if(ksm(2,x,n)==1)//如果找到符合题意的
break;
}
if(flag)
cout << "2^" << x << " mod " << n << " = 1" << endl;
else
cout << "2^? mod " << n << " = 1" << endl;
}
}