The Luckiest Number 欧拉函数

本文介绍了一种通过数学方法寻找特定数字序列周期的方法,并提供了一段C++代码实现。利用欧拉定理和数论原理,文章展示了如何解决这类问题,并确保了算法的时间效率。

The Luckiest Number

Sol:

直接上一波转化:
\[ \overbrace{88......88}^x=8*(10^x-1)/9 \]
那么:
\[ L\ |\ \overbrace{88......88}^x\iff L\ |\ 8*(10^x-1)/9\iff 9L\ |\ 8*(10^x-1) \]
设d=gcd(L,8),那么上式又等价于:
\[ \frac{9L}{d}\ |\ 10^x-1\iff 10^x\equiv1\ (mod\ \frac{9L}{d}) \]
此时可以采取直接枚举x的形式,但是难保证时间,所以需要更好的性质。

引理:

若整数a,n互质,那么有:
\[ 方程\ a^x\equiv 1\ (mod\ n)\\ 最小正整数解x_0是\phi(n)的约数 \]

证明:

反证法。设存在最小整数解x0,那么令:
\[ \phi(n)=q*x_0+r \]
结合欧拉定理可知:
\[ a^{\phi(n)}\equiv a^{q*x_0+r}\equiv 1\ (mod\ n) \]
又因为:
\[ a^{x_0}\equiv 1\ (mod\ n) \]
所以:
\[ a^{q*x_0}\equiv 1\ (mod\ n) \]
所以:
\[ a^{q*x_0+r}\equiv a^{q*x_0}*a^r\equiv a^r \equiv 1\ (mod\ n) \]
显然r<x0,与假设矛盾。

证毕

所以可以求出欧拉函数,然后试除法枚举其约数即可。

#include<string>
#include<cstdio>
#include<cstring>
#define RG register
#define IL inline
#define int unsigned long long
#define DB double
#define INF 1e18
using namespace std;

IL int gi() {
    char ch=0;int x=0,fl=0;
    while (ch>'9'||ch<'0') {if (ch=='-') fl=1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
    return fl?-x:x;
}

int n,d,phi;

IL int getgcd(int x,int y) {return y?getgcd(y,x%y):x;}

IL int multi(int a,int b,int mod)
{
    RG int ans=0;
    a%=mod,b%=mod;
    while(b) {
        if(b&1) ans=(ans+a)%mod;
        b>>=1;
        a=(a+a)%mod;
    }
    return ans;
}

IL int getphi(int x) {
    RG int i,ans=x;
    for (i=2;i*i<=x;++i)
        if (x%i==0) {
            ans=ans/i*(i-1);
            while (x%i==0) x/=i;
        }
    if (x>1) ans=ans/x*(x-1);
    return ans;
}

IL bool quick_pow(int P) {
    RG int x=10,ans=1,mod=9*n/d;
    for (;P;P>>=1,x=multi(x,x,mod))
        if (P&1) ans=multi(ans,x,mod);
    return ans==1;
}

signed main()
{
    RG int i,sum,T=0;
    for (n=gi();n;n=gi()) {
        d=getgcd(8,n);
        if (getgcd(9*n/d,10)==1) {
            sum=phi=getphi(9*n/d);
            for (i=1;i*i<=phi;++i) 
                if (phi%i==0) {
                    if (phi!=i*i&&quick_pow(phi/i)) sum=min(sum,phi/i);
                    if (quick_pow(i)) {sum=i;break;}
                }
            printf("Case %lld: %lld\n",++T,sum);
        }
        else printf("Case %lld: 0\n",++T);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Bhllx/p/10653717.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值