• [luogu] P4861 按钮


    [luogu] P4861 按钮


    1.题目

    题目背景

    (Ada)被关在了一个房间里。

    题目描述

    房间的铁门上有一个按钮,还有一个显示屏显示着“1”。

    旁边还有一行小字:“这是一个高精度(M)进制计算器,每按一次按钮,屏幕上的数便会乘以(K)。当个位数再次变为(1)时,门就开了。”

    由于(Ada)急于出去,所以你要在(1s)之内求出她的最小按键次数。

    输入输出格式

    输入格式:

    一行,两个整数(M)(K)

    输出格式:

    一行一个数字,表示最小按键次数。
    如果无论(Ada)按多少次都无法让门打开,输出"Let's go Blue Jays!"(不含引号)。

    输入输出样例

    输入样例#1:

    11 2
    

    输出样例#1:

    10
    

    输入样例#2:

    6 26
    

    输出样例#2:

    Let's go Blue Jays!
    

    说明

    对于(30\%)的数据,(2 leqslant M,K leqslant 10^4)

    对于(100\%)的数据,(2 leqslant M,K leqslant 2×10^9)

    (Update):我们不认为个位为11,21,...为问题的解(例如,11在16进制下记为B)

    2.题解

    数竟出的题真恐怖

    30pts

    可以开一个(unordered_map)判重,然后模拟乘的过程。

    不用想,对是对,但是你280ms过是不存在的。

    100pts

    考虑求(K^r equiv 1 (mod~M))最小解( (r) 在数论中称作阶)。此方程有解当且仅当(gcd(K, M) = 1)

    假设所求方程中(gcd(K, M) = 1),则由欧拉定理得(K^{phi(M)} equiv 1(mod~M))。但(phi(M))不一定是最小的(r)

    阶有一个善良的性质,即(r | phi(M))。这样我们可以(O(sqrt{phi(M)}))枚举因子,然后求可以使方程成立的因子的最小值即可。

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    typedef long long ll;
    ll k, m, ans(0x7ffffffffffff), a(1);
    using std::swap; using std::exit; using std::min;
    inline ll gcd(ll a, ll b){
        if(a < b) swap(a, b);
        return (!(b) ? a : gcd(b, a % b)); 
    }
    inline ll euler_phi(ll x) {
        ll ans(x), tmp(x);
        ll xx = ll(ceill(sqrtl((long double)x)));
        for (ll i = 2; i <= xx; ++i) 
            if(!(tmp % i)) {
                ans = ans / i * (i - 1);
                while(!(tmp % i)) tmp /= i;
            }
        if(tmp > 1) ans = ans / tmp * (tmp - 1);
        return ans;
    }
    inline ll f_pow(ll a, ll b) {
        ll base(a), ans(1);
        while(b) {
            if(b & 1) ans = (ans * base) % m;
            base = (base * base) % m;
            b >>= 1;
        }
        return ans;
    }
    int main() {
        scanf("%lld%lld", &m, &k);
        if(gcd(m, k) != 1) {puts("Let's go Blue Jays!"); exit(0);}
        ll phi = euler_phi(m);
        ll p = ll(ceill(sqrtl((long double)phi)));
        for (ll i = 1; i <= p; ++i)
            if(!(phi % i)) {
                (f_pow(k, i) == 1) ? ans = min(ans, i) : false;
                (f_pow(k, phi / i) == 1) ? ans = min(ans, phi / i) : false;
            }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    Spring Boot将Mybatis返回结果转为驼峰的三种实现方式
    Lodash-一个好用的JavaScript工具库
    基于Docker搭建LNMP环境并启用ssl证书(certbot)
    CentOS忘记mariadb/mysql root密码解决办法
    Debian如何安装curl?
    SpringBoot Controller如何接收数组参数?
    nginx web服务器概念了解 配置
    c语言二维数组的转置
    顺序表有序插入数据
    elasticsearch master_not_discovered_exception
  • 原文地址:https://www.cnblogs.com/manziqi/p/9874649.html
Copyright © 2020-2023  润新知