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∗(10x−1)/9,因为
L
L
L可以整除它,所以有:
8
∗
(
1
0
x
−
1
)
/
9
=
k
∗
L
8*(10^x-1)/9=k*L
8∗(10x−1)/9=k∗L,即
8
∗
(
1
0
x
−
1
)
=
k
∗
9
∗
L
8*(10^x-1)=k*9*L
8∗(10x−1)=k∗9∗L,两边同时消去
g
c
d
(
9
∗
L
,
8
)
gcd(9*L,8)
gcd(9∗L,8),可得
p
∗
(
1
0
x
−
1
)
=
k
∗
q
p*(10^x-1)=k*q
p∗(10x−1)=k∗q,其中
p
=
8
/
g
c
d
(
9
∗
L
,
8
)
p=8/gcd(9*L,8)
p=8/gcd(9∗L,8),
q
=
9
∗
L
/
g
c
d
(
9
∗
L
,
8
)
q=9*L/gcd(9*L,8)
q=9∗L/gcd(9∗L,8),那么
p
、
q
p、q
p、q一定是互质的,所以有
(
1
0
x
−
1
)
=
0
m
o
d
q
(10^x-1)=0\ mod\ q
(10x−1)=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;
}