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;
}

 

转载于:https://www.cnblogs.com/mysh/p/11333675.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值