B - 2^x mod n = 1
一、题目
输入一个n,来寻找一个最小的x,使得2^ x mod n = 1 成立,并输出2^ x mod n = 1 。
若不存在这样的x,则输出2^? mod n = 1。
例如:
当n=2时,不存在x满足条件,则输出2^? mod 2 = 1。
当n=5时,可以找到最小的x=4,所以输出2^4 mod 5 = 1。
二、思路
首先会想到的应该是暴力模拟了,写一个循环,来寻找x。当然,不可能无限的找下去,因为存在不存在x的情况,并且还会出现 tle 的情况,所以这个方法不可行。
但在没有其他方法解决的时候,只能硬着头皮上了。这个循环的代码很容易写出来,但还是有需要注意的地方。
因为x可能会特别的大,而2^x会成指数级的增长,因此我们需要在运算过程中对2 ^x进行取余,即每当乘2时都需要mod n,以确保2 ^x 不会炸掉,并且对最后的结果没有产生影响。
三、代码
#include<stdio.h>
int main()
{
long i,n,p;
while(scanf("%d",&n)!=EOF)
{
p=2;
for (i=1;i<=1000000;++i)
{
p=p*2%n;
if (p==1) break;
}
if (i<=1000000) printf("2^%d mod %d = 1\n",i+1,n);
else printf("2^? mod %d = 1\n",n);
}
return 0;
}
这个代码a了本题,但讨论还没有结束!
四、缺陷
很明显,我们不能确定 i 的循环范围。
首先我们假设当循环 10^7 次是时会 tle,输出的结果需要 10^5 次,那当 i 小于10^5时会WA,大于 10^7会 tle ,那么 i 的范围就是 10^ 7到10^ 5。但是数据并不一定想象的那样,随着 n 的增大, i 的循环范围与需要加大,所以可以AC的范围会越来越小,直到不存在这种范围,即10^7 以下全WA,10^7 以上全tle,所以我们需要找到一种更优的算法,来解决这个问题!
五、费马-欧拉定理
关于如何优化,我们先来看看一个定理——费马-欧拉定理。
对于互质的两个数a,p,存在这样一个等式
aφ(p) ≡ 1(mod p)
其中φ(p)是1 到 p-1当中与 p 互质的数的个数
六、优化
题目中a为2,所以所有的奇数都与a互质,而偶数不行,因此当输入的n为偶数是一定不行,而后我们只需求奇数的结果。(特例:当n=1时也不行哦)
从而避免了WA的情况!但tle还没避免!
七、小结
我曾考虑过试图求φ(p)的值当作结果,但出现的问题!
当n=7时,求得φ(n)=6,虽然x=6可以时等式成立,但并不是最优解,因为x=3时也可以使等式成立!
所以如何避免tle还在考虑中!