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;
}
posted @ 2018-03-05 09:19  poorpool  阅读(179)  评论(0编辑  收藏  举报