最幸运的数字
8是中国的幸运数字,如果一个数字的每一位都由8构成则该数字被称作是幸运数字。
现在给定一个正整数L,请问至少多少个8连在一起组成的正整数(即最小幸运数字)是L的倍数。
输入格式
输入包含多组测试用例。
每组测试用例占一行,包含一个整数L。
当输入用例L=0时,表示输入终止,该用例无需处理。
输出格式
每组测试用例输出结果占一行。
结果为“Case 1: ”+一个整数N,N代表满足条件的最小幸运数字的位数。
如果满足条件的幸运数字不存在,则N=0。
数据范围
1
≤
L
≤
2
∗
1
0
9
1≤L≤2∗10^9
1≤L≤2∗109
输入样例:
8
11
16
0
输出样例:
Case 1: 1
Case 2: 2
Case 3: 0
题解:
题目好是好,但是也是太恶心了吧。想到了正解,谁又想到Long long也爆了呢。
正解:
8.....8
=
8
∗
1....1
=
8
∗
9....9
9
=
8
9
∗
(
1
0
x
−
1
)
8.....8=8*1....1=8*\frac{9....9}{9}=\frac{8}{9}*(10^x-1)
8.....8=8∗1....1=8∗99....9=98∗(10x−1)
上述的数字是L的倍数等价于L能被他们整除,所以L是他们的约数
L
∣
8
9
∗
1
0
x
−
1
L|\frac{8}{9}*10^x-1
L∣98∗10x−1
L
∗
9
∣
8
∗
1
0
x
−
1
L*9|8*10^x-1
L∗9∣8∗10x−1
因为8和9互质所以我们要约掉8就是除以
(
L
,
8
)
[
(
a
,
b
)
表
示
a
,
b
的
g
c
d
]
(L,8)[(a,b)表示a,b的gcd]
(L,8)[(a,b)表示a,b的gcd]
所以化简得到
L
1
=
1
0
x
−
1
。
L
1
=
9
∗
l
(
L
,
8
)
L_1=10^x-1。L_1=\frac{9*l}{(L,8)}
L1=10x−1。L1=(L,8)9∗l
等价
1
0
x
≡
1
(
m
o
d
L
1
)
10^x≡ 1(mod L_1)
10x≡1(modL1)不会打同余符号
这个和我们欧拉定理是不是很像。我们把x换成
p
h
i
(
L
1
)
phi(L_1)
phi(L1)就是我们欧拉定理了。
根据欧拉定理我们知道,只有当我们
L
1
和
10
互
质
的
时
候
才
是
有
解
的
。
L_1和10互质的时候才是有解的。
L1和10互质的时候才是有解的。
并且这里我们的最小解是
p
h
i
(
L
1
)
phi(L_1)
phi(L1)的最小约数。
证明如下:
利用反正法,最小解X不是我们的最小约数,则
p
h
i
(
L
1
)
=
x
∗
k
+
r
(
1
<
r
<
x
)
phi(L_1)=x*k+r(1<r<x)
phi(L1)=x∗k+r(1<r<x)
整理上述条件
1
0
x
≡
1
(
m
o
d
L
1
)
10^x≡ 1(mod L_1)
10x≡1(modL1)
所以
1
0
q
x
≡
1
(
m
o
d
L
1
)
10^{qx}≡ 1(mod L_1)
10qx≡1(modL1)
1
0
p
h
i
(
L
1
)
≡
1
(
m
o
d
L
1
)
10^{phi(L_1)}≡ 1(mod L_1)
10phi(L1)≡1(modL1) 可以得到
1
0
r
≡
1
(
m
o
d
L
1
)
10^{r}≡ 1(mod L_1)
10r≡1(modL1)
因为r<x所以于假设矛盾。即最小解x是我们的最小约数。
所以答案也就变成了在
p
h
i
(
L
1
)
phi(L_1)
phi(L1)的约数中找一个最小的。
最后记得用龟速乘。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int qmul(int a, int k, int b)
{
int res = 0;
while (k)
{
if (k & 1) res = (res + a) % b;
a = (a + a) % b;
k >>= 1;
}
return res;
}
int q_pow(int a,int k,int b)
{
int res=1;
while(k){
if(k&1) res=qmul(res,a,b);
a=qmul(a,a,b);
k>>=1;
}
return res;
}
int get_euler(int c)
{
int res=c;
for(int i=2;i<=c/i;i++){
if(c%i==0){
while(c%i==0) c/=i;
res=res/i*(i-1);
}
}
if(c>1) res=res/c*(c-1);
return res;
}
signed main()
{
int T=1;
long long n;
while(cin>>n,n){
int d=1;
while(n%(d*2)==0&&d * 2 <= 8) d*=2;
int C=9*n/d;
int res=1e18;
if(C%2==0||C%5==0) res=0;
int phi=get_euler(C);
for(int i=1;i*i<=phi;i++){
if(phi%i==0){
if(q_pow(10,i,C)==1) res=min(res,i);
if(q_pow(10,phi/i,C)==1) res=min(res,phi/i);
}
}
printf("Case %d: %lld\n", T ++, res);
}
}