P4861 按钮
题目背景
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; }