图片来自:http://blog.csdn.net/u012936765/article/details/38776799
证明来自:https://github.com/faxinwang/2017_summer_train/blob/master/3.欧拉定理-最小x.cpp#L40
题目内容:
给定一个n, 求满足 2^x =1 (mod n)的最小x(x>0).
输入描述
输入整数n
输出描述
输出最小的x, 或者输出“不存在”
输入样例
5
输出样例
4
欧拉函数:对于正整数N,代表小于等于N的与N互质的数的个数,记作φ(N)
欧拉定理:a^(φ(m))同余1(mod m) (a与m互质,如果a,m不互质。如2^x=1(mod 6) 则x必定无解)
思路:在解决该题过程中,可以先将欧拉函数求出,令欧拉函数为t。虽然满足2^t=1(mod n)但是,t不一定是最小解!
如:当n=7时,φ(n)=6 (1,2,3,4,5,6满足与6互质) 所以有2^6=1(mod 7),但是明显4不是最小解,最小解应该是3。2^3=1(mod 7)!
所以有:如果x是满足a^x==1 (mod n)的最小正数解,则 x一定是φ(n)的约数(注意并不是所有的约数都满足a^x==1 (mod n) )
证明:
如果x是满足ax≡1 (mod n)的最小的正x, 则x<= φ(n)
则令φ(n)=tx+d, 其中余数d小于x, 则 a^φ(n)=a^(tx+d)=a^tx * a^d
因此满足a^d=1(mod n) , 由于x是最小的,因此只好d=0
故x整除φ(n)
后面要做的事情就是找出这个约数,题目就解决完成了。
欧拉函数模版:
int euler(int n) { //欧拉函数的实现
int res = n, a = n;
for (int i = 2;i*i <= a;i++) {
if (a%i == 0) {
res = res / i*(i - 1);//先进行除法是为了防止中间数据的溢出
while (a%i == 0) a /= i;
}
}
if (a>1) res = res / a*(a - 1);
return res;
}
题目代码:
//给定一个n, 求满足 2^x =1 (mod n)的最小x(x>0).
#include <iostream>
using namespace std;
int euler(int n) { //欧拉函数的实现
int res = n, a = n;
for (int i = 2; i*i <= a; i++) {
if (a%i == 0) {
res = res / i*(i - 1);//先进行除法是为了防止中间数据的溢出
while (a%i == 0) a /= i;
}
}
if (a>1) res = res / a*(a - 1);
return res;
}
int poww(int a, int b, int mod)//a^b % mod
{
int ans = 1;
int base = a%mod;
while (b > 0)
{
if ((b & 1) == 1)
ans = (ans*base) % mod;
base = (base*base) % mod;
b = b >> 1;
}
return ans;
}
int main()
{
int n;
cin >> n;
if (n == 0 || n % 2 == 0)
{
cout << "不存在" << endl;
return 0;
}
int t = euler(n);
//2^t=1(mod n)
for(int i=1;i<=t;i++)
if (t%i == 0 && poww(2, i, n) == 1)//取t的约数
{
cout << i << endl;
// system("pause");
return 0;
}
//cout << "不存在" << endl;
//system("pause");
return 0;
}