POJ 3696 The Luckiest number 欧拉定理

本文探讨了一道算法题目,目标是找到最小的全由8组成的数,该数为给定数L的倍数。通过数学推导,利用欧拉定理和快速幂运算,实现了高效求解。注意避免数据溢出问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://vjudge.net/problem/POJ-3696
在这里插入图片描述题目大意:给一个数 L L L,让你找到最小的一个数 x x x使得 x x x L L L的倍数且它的每一位都是 8 8 8,如果存在这样的 x x x,请输出它的位数,否则输出 0 0 0
思路:由 8 8 8组成的数可以表示成 8 ∗ ( 1 0 x − 1 ) / 9 8*(10^x-1)/9 8(10x1)/9,因为 L L L可以整除它,所以有: 8 ∗ ( 1 0 x − 1 ) / 9 = k ∗ L 8*(10^x-1)/9=k*L 8(10x1)/9=kL,即 8 ∗ ( 1 0 x − 1 ) = k ∗ 9 ∗ L 8*(10^x-1)=k*9*L 8(10x1)=k9L,两边同时消去 g c d ( 9 ∗ L , 8 ) gcd(9*L,8) gcd(9L,8),可得 p ∗ ( 1 0 x − 1 ) = k ∗ q p*(10^x-1)=k*q p(10x1)=kq,其中 p = 8 / g c d ( 9 ∗ L , 8 ) p=8/gcd(9*L,8) p=8/gcd(9L,8) q = 9 ∗ L / g c d ( 9 ∗ L , 8 ) q=9*L/gcd(9*L,8) q=9L/gcd(9L,8),那么 p 、 q p、q pq一定是互质的,所以有 ( 1 0 x − 1 ) = 0   m o d   q (10^x-1)=0\ mod\ q (10x1)=0 mod q,也即 1 0 x = 1   m o d   q 10^x=1\ mod\ q 10x=1 mod q。推到此处,不难发现需要用到欧拉定理,如果 g c d ( 10 , q ) = 1 gcd(10,q)=1 gcd(10,q)=1,那么答案一定存在于 φ ( q ) φ(q) φ(q)的所有因子中,枚举判断取最小值即可;否则说明无解。此题还有一个坑点就是快速幂直接用乘法会爆 l o n g   l o n g long\ long long long,需要注意一下。

#include<cstdio>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

ll fmul(ll a,ll b,ll p)
{
    return (a*b-(ll)((long double)a*b/p)*p+p)%p;
}

ll qpow(ll a,ll b,ll p)
{
    ll ans=1;
    a%=p;
    while(b)
    {
        if(b&1)
            ans=fmul(ans,a,p);
        a=fmul(a,a,p);
        b>>=1;
    }
    return ans;
}

ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}

ll euler(ll n)
{
    ll ans=n;
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
            n/=i,ans-=ans/i;
        while(n%i==0)
            n/=i;
    }
    if(n>1)
        ans-=ans/n;
    return ans;
}

int main()
{
    ll x;
    int times=0;
    while(~scanf("%lld",&x)&&x)
    {
        printf("Case %d: ",++times);
        x=9*x/gcd(8,x);
        if(gcd(10,x)==1)
        {
            ll oula=euler(x),a,b;
            ll ans=oula;
            for(ll i=1;i*i<=oula;i++)
            {
                if(oula%i==0)
                {
                    a=i,b=oula/i;
                    if(qpow(10,a,x)==1)
                        ans=min(ans,a);
                    if(a!=b&&qpow(10,b,x)==1)
                        ans=min(ans,b);
                }
            }
            printf("%lld\n",ans);
        }
        else
            printf("0\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值