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