poj3696 The Luckiest number
即求出一个 \(x\) 使得 \(L|8 \times (10^x-1)/9\),记 \(d=(L,8)\)。
\[L|8 \times (10^x-1)/9 \Leftrightarrow \frac{9L}{d}|(10^x-1) \Leftrightarrow 10^x \equiv 1 \pmod {\frac{9L}{d}}
\]
有引理: 若 \((a,n)=1\),则满足 \(a^x \equiv 1 \pmod n\) 的最小 \(x\) 必为 \(\varphi(n)\) 的约数。
证明: 假设不可,则 \(\varphi(n)=qx+r\),\(a^x \equiv 1 \pmod n \Leftrightarrow a^{qx} \equiv 1 \pmod n\),又 \(a^{\varphi(n)} \equiv 1 \pmod n\),则 \(a^r \equiv 1 \pmod n\)。\(r<x\),矛盾,证毕。
因此枚举 \(\varphi(9L/d)\) 的约数一一验证即可。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll l, ans;
int n;
ll gcd(ll a, ll b){
return !b?a:gcd(b, a%b);
}
ll getPhi(ll x){
ll re=x;
for(ll i=2; i*i<=x; i++)
if(x%i==0){
re = re / i * (i - 1);
while(x%i==0) x /= i;
}
if(x>1) re = re / x * (x - 1);
return re;
}
ll mul(ll a, ll b, ll p){
ll re=0;
while(b){
if(b&1) re = (re + a) % p;
a = (a + a) % p;
b >>= 1;
}
return re;
}
ll ksm(ll a, ll b, ll p){
ll re=1;
while(b){
if(b&1) re = mul(re, a, p);
a = mul(a, a, p);
b >>= 1;
}
return re;
}
int main(){
while(scanf("%lld", &l)!=EOF){
if(!l) break;
ans = 0x3f3f3f3f3f3f3f3f;
ll d=gcd(l, 8);
ll phi=getPhi(9*l/d);
for(ll i=1; i*i<=phi; i++)
if(phi%i==0){
if(ksm(10, i, 9*l/d)==1)
ans = min(ans, i);
if(ksm(10, phi/i, 9*l/d)==1)
ans = min(ans, phi/i);
}
printf("Case %d: %lld\n", ++n, ans==0x3f3f3f3f3f3f3f3f?0:ans);
}
return 0;
}
拙いものと思えども、
その手に握る其れこそが、
いつか幻想を生んでいく。