hdu 1395(欧拉函数)

2^x mod n = 1

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 15810    Accepted Submission(s): 4914


Problem Description
Give a number n, find the minimum x(x>0) 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
这里提供两种方法来做,暴力或者欧拉函数。但是暴力我感觉的话数据量大一点可能就AC不了了。
暴力做法(大一的时候写的):
#include<math.h>
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int n=1000000;
int quick_pow_mod(int a,int b,int c)
{
    int ans=1;
    while(b>0)
    {
        if(b&1)
            ans=(a*ans)%c;
        b=b>>1;
        a=(a*a)%c;
    }
    return ans;
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int flag=1,t,k;
        if(n%2==0 || n==1) printf("2^? mod %d = 1\n",n);   //n=1!!!!!!!!
        else
        {
            for(int i=1; ; i++)
            {
                k=quick_pow_mod(2,i,n);
                if(k==1)
                {
                    t=i;
                    flag=0;
                    break;
                }
            }
            if(flag)
                printf("2^? mod %d = 1\n",n);
            else printf("2^%d mod %d = 1\n",t,n);
        }

    }
}

欧拉函数:

用φ(n)表示不大于n且与n互素的数的个数,该函数以欧拉的名字命名,称为欧拉函数。

      如果n是一个素数,即n = p,那么φ(n) = p-1(所有小于n的都互素);
      如果n是素数的k次幂,即n = p^k,那么φ(n) = p^k - p^(k-1) (除了p的倍数其它都互素);
      如果m和n互素,那么φ(mn) = φ(m)φ(n)(可以利用上面两个性质进行推导)。
      将n分解成如图二-4-1的素因子形式,那么利用上面的定理可得φ(n)
欧拉定理:若n,a为正整数,且n,a互素,则: 
但是我们求出的欧拉函数并不是这个方程最小的解。它的解有可能在它的因子中,这个是可以证明的。这里就不详细证明了。分解因子然后得到最小的解。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
using namespace std;
typedef long long LL;
const int N = 10000;
bool p[N];
int euler[N];
int e[N];
void getEuler()
{
    memset(euler,0,sizeof(euler));
    euler[1] = 1;
    for(int i = 2; i <= N; i++)
        if(!euler[i])
            for(int j = i; j <= N; j+= i)
            {
                if(!euler[j])
                    euler[j] = j;
                euler[j] = euler[j]/i*(i-1);
            }
}
int pow_mod(int a,int b,int mod)
{
    int ans = 1;
    while(b)
    {
        if(b&1) ans = ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
    getEuler();
    int n;
    while(~scanf("%d",&n))
    {
        if(n%2&&n!=1)
        {
            int m = euler[n];
            memset(e,0,sizeof(e));
            int id=0;
            e[id++] = m;
            for(int i=2; i*i<=m; i++) ///分解出m所有的因子
            {
                if(m%i==0)
                {
                    if(i*i==m) e[id++] =i;
                    else
                    {
                        e[id++]=i;
                        e[id++]=m/i;
                    }
                }
            }
            sort(e,e+id);
            int ans = m;
            for(int i=0; i<id; i++)
            {
                if(pow_mod(2,e[i],n)==1)
                {
                    ans = e[i];
                    break;
                }
            }
            printf("2^%d mod %d = 1\n",ans,n);
        }
        else printf("2^? mod %d = 1\n",n);
    }
    return 0;
}

 

posted @ 2016-05-26 17:27  樱花庄的龙之介大人  阅读(462)  评论(0编辑  收藏  举报