The Luckiest number(同余+欧拉定理)

题目传送门

单词小讲堂

consist 组成
multiple 倍数
construct 构建,构造

题目大意

这个题的意思就是说,中国人认为8是吉祥数,当然了鲍勃有自己的吉祥数L,但是鲍勃喜欢中国女生,所以希望自己的吉祥数L的倍数可以是8888888……(n个8),下面给出一些L请你找出这些8的最小位数,如果不行,输出0即可!

思路

公式预警!!
考虑到 8888888 … … = ( 100000000000 … … − 1 ) ∗ 8 9 8888888……=(100000000000……-1)*\frac{8}{9} 8888888=(1000000000001)98
因此这道题就可以表示为 L ∣ 8 9 ∗ ( 1 0 y − 1 ) L|\frac{8}{9}*(10^y-1) L98(10y1)
9 L ∣ 8 ∗ ( 1 0 y − 1 ) 9L|8*(10^y-1) 9L8(10y1)
两边同时除以 g c d ( 9 L , 8 ) gcd(9L,8) gcd(9L,8)
9 L g c d ( 9 L , 8 ) ∣ 8 g c d ( 9 L , 8 ) ∗ ( 1 0 y − 1 ) \frac{9L}{gcd(9L,8)}|\frac{8}{gcd(9L,8)}*(10^y-1) gcd(9L,8)9Lgcd(9L,8)8(10y1)
那么现在 9 L g c d ( 9 L , 8 ) 和 8 g c d ( 9 L , 8 ) \frac{9L}{gcd(9L,8)} 和\frac{8}{gcd(9L,8)} gcd(9L,8)9Lgcd(9L,8)8互质
因此 9 L g c d ( 9 L , 8 ) ∣ ( 1 0 y − 1 ) \frac{9L}{gcd(9L,8)}|(10^y-1) gcd(9L,8)9L(10y1)结果就是 y y y的最小值
为嘛?因为 8 g c d ( 9 L , 8 ) \frac{8}{gcd(9L,8)} gcd(9L,8)8是小于 10 10 10的数,因此位数就是 y y y的值。
n = 9 L g c d ( 9 L , 8 ) n=\frac{9L}{gcd(9L,8)} n=gcd(9L,8)9L
转化成为了 k ∗ n = 1 0 y − 1 k*n=10^y-1 kn=10y1
啊,这不就是我们的同余公式嘛
1 0 y ≡ 1 ( m o d n ) 10^y≡1(mod n) 10y1(modn)
好了,现在我们只需要求 y y y的值就可以了!
下面我们介绍拓展欧拉定理的一个小结论

若正整数 a , n a,n a,n互质,则满足 a x ≡ 1 ( m o d n ) a^x≡1(mod n) ax1(modn)的最小正整数 x 0 x_0 x0 φ ( n ) φ(n) φ(n)的约数(可以利用反证法证明该结论)

那么我们现在逐一枚举 φ ( n ) φ(n) φ(n)的因子,就可以了。(需要快速幂优化)

#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll phi(ll x)
{
    ll res = x;
    for (ll i = 2; i <= x / i; i ++ )
        if (x % i == 0)
        {
            res = res / i * (i - 1);
            while (x % i == 0) x /= i;
        }
    if (x > 1) res = res / x * (x - 1);

    return res;
}
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll qmi(ll m, ll k, ll p)
{
    ll res = 1 % p, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}

int main(){
    ll n,t=0;
    while(cin>>n&&n){
        ll k=gcd(9*n,8);
        //if(k==1){
        //    cout<<"Case "<<++t<<": 0\n";
        //    continue;
        //}
        ll p=9*n/k;
        if(gcd(p,10)!=1){
            cout<<"Case "<<++t<<": 0\n";
            continue;
        }
        ll e=phi(p);
        int ju=0;
        for(ll i=1;i<=e/i;i++){
            if(e%i==0&&qmi(10,i,p)==1){
                printf("Case %lld: %lld\n",++t,i);
                ju=1;
                break;
            }
        }
        if(ju)continue;
        for(ll i=sqrt(e);i>=1;i--){
            if(e%(e/i)==0&&qmi(10,e/i,p)==1){
                printf("Case %lld: %lld\n",++t,e/i);
                break;
            }
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值