题目背景
Ada被关在了一个房间里。
题目描述
房间的铁门上有一个按钮,还有一个显示屏显示着“1”。 旁边还有一行小字:“这是一个高精度M进制计算器,每按一次按钮,屏幕上的数便会乘以K。当个位数再次变为1时,门就开了。” 由于Ada急于出去,所以你要在1s之内求出她的最小按键次数。
输入格式:
一行,两个整数M和K。
输出格式:
一行一个数字,表示最小按键次数。 如果无论Ada按多少次都无法让门打开,输出"Let's go Blue Jays!"(不含引号)。
输入样例
11 2
输出样例
10
输入样例
6 26
输出样例
Let's go Blue Jays!
说明
对于30%的数据,2≤M,K≤10^4
对于100%的数据,2≤M,K≤2×10^9
update:
我们不认为个位为11,21,...为问题的解(例如,11在16进制下记为B
思路:
若gcd(K,M)!=1,则无解。
因为k^x mod M一定是gcd(K,M)的倍数。
由扩展欧几里得&&中国同余定理可知最小的解x一定整除φ(M)
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int m,k;
int ans,ans1;
long long x,y;
int ty(int x,int y) {
int ans=1;
for (; y; y>>=1,x=(long long)x*x%m)
if(y&1)
ans=(long long)ans*x%m;
return ans;
}
int gcd(int a,int b) {
if(a<b)
swap(a,b);
if(a%b==0)
return b;
else
return gcd(b,a%b);
}
int zc(int n) {
int ret=n;
for (int i=2; i*i<=n; i++)
if (n%i==0) {
ret=ret/i*(i-1);
do n/=i;
while(n%i==0);
}
if (n>1)
ret=ret/n*(n-1);
return ret;
}
int main () {
scanf("%d%d",&m,&k);
if(gcd(m,k)!=1) {
printf("Let's go Blue Jays!\n");
return 0;
} else {
ans=ans1=zc(m);
for(int i=2; i*i<=ans1; i++)
if(ans1%i==0) {
if(ty(k,i)==1)
ans=min(ans,i);
if(ty(k,ans1/i)==1)
ans=min(ans,ans1/i);
}
printf("%d\n",ans);
}
return 0;
}