题目
求是否存在一个数 x = 888...888 x=888...888 x=888...888使得 L ∣ x L|x L∣x
分析
首先这道题的这个数可以表示为
8
(
1
0
x
−
1
)
÷
9
8(10^x-1)\div9
8(10x−1)÷9,然后求的就是最小的
x
x
x.
L
∣
8
(
1
0
x
−
1
)
÷
9
=
9
L
∣
8
(
1
0
x
−
1
)
=
9
L
g
c
d
(
L
,
8
)
∣
1
0
x
−
1
=
1
0
x
≡
1
(
m
o
d
9
L
g
c
d
(
L
,
8
)
)
L|8(10^x-1)\div9=9L|8(10^x-1)=\frac{9L}{gcd(L,8)}|10^x-1=10^x\equiv 1(mod \frac{9L}{gcd(L,8)})
L∣8(10x−1)÷9=9L∣8(10x−1)=gcd(L,8)9L∣10x−1=10x≡1(modgcd(L,8)9L),然后可以发现用欧拉定理
a
φ
(
9
L
g
c
d
(
L
,
8
)
)
≡
1
(
m
o
d
9
L
g
c
d
(
L
,
8
)
)
a^{\varphi(\dfrac{9L}{gcd(L,8)})}\equiv1(mod \frac{9L}{gcd(L,8)})
aφ(gcd(L,8)9L)≡1(modgcd(L,8)9L)
然后枚举约数
φ
(
9
L
g
c
d
(
L
,
8
)
)
\varphi(\dfrac{9L}{gcd(L,8)})
φ(gcd(L,8)9L)的约数就行了,时间复杂度
O
(
L
log
L
)
O(\sqrt L \log L)
O(LlogL)
代码
#include <cstdio>
typedef long long ll; ll cnt;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mul(ll x,ll y,ll mod){//因为乘法可能溢出,所以再用一次快速幂的思想做乘法
ll ans=0;
while (y){
if (y&1) ans=(ans+x)%mod;
x=(x<<1)%mod; y>>=1;
}
return ans;
}
ll ksm(ll x,ll y,ll mod){//快速幂
ll ans=1;
while (y){
if (y&1) ans=mul(ans,x,mod);
x=mul(x,x,mod); y>>=1;
}
return (ans-1)*8%mod;//9L|8(10^x-1)
}
void print(ll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
ll euler(ll n){//求欧拉函数
ll ans=n;
for (register int i=2;i*i<=n;i++)
if (n%i==0){
ans-=ans/i;
while (n%i==0) n/=i;
}
if (n>1) ans-=ans/n;
return ans;
}
int main(){
while (1){
char c=getchar(); ll l=0;
while (c<48||c>57) c=getchar();
while (c>47&&c<58) l=(l<<3)+(l<<1)+c-48,c=getchar();
if (!l) return 0;
printf("Case %d: ",++cnt);
ll m=9*l/gcd(l,8);
if (gcd(10,m)!=1) putchar('0'),putchar('\n');
else {
ll n=euler(m),ans=n;
for (int i=2;i*i<n;i++)//枚举约数
if (n%i==0){
ll cnt=0;
while (n%i==0) n/=i,cnt++;
while (cnt)
if (!ksm(10,ans/i,9*l)) ans/=i,cnt--; else break;
}
if (n>1) if (!ksm(10,ans/n,9*l)) ans/=n;
print(ans); putchar('\n');
}
}
}