前言
update 2021.7.23 加上了句号,但是丑陋的 (LaTeX) 使用没有改。
差一点就推出来了qaq。
题目
题目大意:
多组询问,0结束,问(x=88...888)(len个(8)),且(L|x)的最小(len),如果无解输出(0)。
输出格式见样例。
讲解
首先我们可以将(x)表示为((10^{len}-1)/9*8)。
那么(L|(10^{len}-1)/9*8),(L*9|(10^{len}-1)*8)。
令(d=gcd(L*9,8)),所以(L*9/d|(10^{len}-1)*8/d)。
令(L'=L*9/d),因为(L*9/d)与(8/d)互质,所以(L'|(10^{len}-1))。
那么一定可以写成这种形式:(10^{len}\% L'=1)。
此时如果(10)与(L')不互质,一定无解。
否则(10^{phi(L')}\% L'=1),(phi(L'))即为答案。
吗?
我们要求最小的答案,所以我们需要枚举(phi(L'))的因数,再用快速幂判断即可。
值得注意的是在快速幂期间,中间变量可能会爆(long long),所以要使用防爆乘法。
代码
LL gcd(LL x,LL y)
{
if(!y) return x;
return gcd(y,x%y);
}
LL getphi(LL x)
{
LL ret = x;
for(int i = 2;1ll * i * i <= x;++ i)
{
if(x % i == 0)
{
ret = ret / i * (i-1);
while(x % i == 0) x /= i;
}
}
if(x > 1) ret = ret / x * (x-1);
return ret;
}
LL gsc(LL x,LL y,LL MOD)
{
LL ret = 0;
while(y){if(y & 1) ret = (ret + x) % MOD;x = (x << 1) % MOD;y >>= 1;}
return ret;
}
LL qpow(LL x,LL y,LL MOD)
{
LL ret = 1;
while(y){if(y & 1) ret = gsc(ret,x,MOD);x = gsc(x,x,MOD);y >>= 1;}
return ret;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
while(1)
{
n = Read();
if(!n) return 0;
n *= 9;
LL d = gcd(n,8),ans,phi;
n /= d;
if(gcd(n,10) > 1) {printf("Case %d: 0
",++tot);continue;}
ans = phi = getphi(n);
for(int i = 1;1ll*i*i <= phi;++ i)
if(phi % i == 0)
{
if(qpow(10,i,n) == 1) {ans = i;break;}
if(qpow(10,phi/i,n) == 1) ans = phi/i;
}
printf("Case %d: %lld
",++tot,ans);
}
return 0;
}