hdu 1395 2^x(mod n) = 1(C++)(欧拉定理 分解素因数)

版权声明:本文为博主原创,未经博主允许不得转载 https://blog.csdn.net/Sherry_Yue/article/details/88595972

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 2 x ( m o d   n ) = 1 2^x(mod\space 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

中文翻译

Problem Description
给出一个数字n,找到满足 2 x ( m o d   n ) = 1 2^x(mod\space n) = 1 的最小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互质,则 a φ ( n ) 1 ( m o d   n ) a^{φ(n)} ≡ 1 (mod\space n)

  1. 当n=1时,明显 2 x ( m o d   1 ) = 1 2^x(mod\space 1) = 1 不成立,所以找不到最小的x。

  2. 当n为偶数时, 2 x 2^x 是偶数,一个偶数模另外一个偶数,明显 2 x ( m o d   n ) = 1 2^x(mod\space n) = 1 也不成立,所以找不到最小的x。

  3. 当n为非1的奇数时,n和2互质,由欧拉定理,令a=2,n为输入的奇数,则根据欧拉函数计算得φ(n),代入欧拉定理得 2 φ ( n ) 1 ( m o d   n ) 2^{φ(n)} ≡ 1 (mod\space n) ,即 2 φ ( n ) ( m o d   n ) = 1 2^{φ(n)} (mod\space n) = 1
    对比题目要求的 2 x ( m o d   n ) = 1 2^x(mod\space n) = 1 ,很容易发现φ(n)必是符合要求的x。
    但φ(n)未必是最小的x,所以就可以从1~φ(n)遍历,找到符合题目 2 x ( m o d   n ) = 1 2^x (mod\space n) = 1 最小的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;
    }
}

猜你喜欢

转载自blog.csdn.net/Sherry_Yue/article/details/88595972
今日推荐