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.
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=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); else printf("2^%d mod %d = 1 ",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 ",ans,n); } else printf("2^? mod %d = 1 ",n); } return 0; }