P O J 3696 POJ3696 POJ3696
- 题目
POJ3696 - 题意
- 分析
x x x个 8 8 8连在一起组成的正整数可写作 8 ( 1 0 x − 1 ) 9 {\frac{8{(10^x-1)}}{9}} 98(10x−1),把题目的问题转化为:求一个最小的 x x x,满足 L ∣ 8 ( 1 0 x − 1 ) / 9 L|8(10^x-1)/9 L∣8(10x−1)/9.- 前提:
g c d ( a c , b c ) = c gcd(ac,bc) = c gcd(ac,bc)=c ⇒ \Rightarrow ⇒ g c d ( a , b ) = 1 gcd(a,b) = 1 gcd(a,b)=1
g c d ( a c g c d ( a c , b c ) , b c g c d ( a c , b c ) ) = 1 gcd({\frac{ac}{gcd(ac,bc)}},{\frac{bc}{gcd(ac,bc)}}) = 1 gcd(gcd(ac,bc)ac,gcd(ac,bc)bc)=1
即:正整数 x , y x,y x,y的最大公约数不为 1 1 1时,可以通过同时除以最大公约数方法使得这两个数互质。
已知 q ∣ p ∗ x , g c d ( p , q ) = 1 q|p*x,gcd(p,q) = 1 q∣p∗x,gcd(p,q)=1 ⇒ \Rightarrow ⇒ q ∣ x q|x q∣x.
推广式:
d ∣ i ∗ j d|i*j d∣i∗j ⇒ \Rightarrow ⇒ d g c d ( i , d ) ∣ j {\frac{d}{gcd(i,d)}|{j}} gcd(i,d)d∣j - 推导:
L ∣ 8 ( 1 0 x − 1 ) 9 ⇔ 9 L ∣ 8 ( 1 0 x − 1 ) L|{\frac{8(10^x-1)}{9}} {\Leftrightarrow} 9L|8(10^x-1) L∣98(10x−1)⇔9L∣8(10x−1)
需要化简成: m ∣ 1 0 x − 1 m|10^x-1 m∣10x−1这样的形式。 8 8 8不能直接除到 9 L 9L 9L那里。所以先
8 ( 1 0 x − 1 ) 9 = k L {\frac{8(10^x-1)}{9}} = kL 98(10x−1)=kL
\qquad ⇓ \Downarrow ⇓
8 ( 1 0 x − 1 ) = 9 k L 8(10^x-1) = 9kL 8(10x−1)=9kL
\qquad ⇓ \Downarrow ⇓
现在是 9 L ∣ 8 ( 1 0 x − 1 ) 9L|8(10^x-1) 9L∣8(10x−1) g c d ( L , 8 ) gcd(L,8) gcd(L,8)不一定等于 1 1 1,所以需要等式两边同时除以 g c d ( 8 , L ) gcd(8,L) gcd(8,L),使得满足等式两边 g c d gcd gcd等于 1 1 1
\qquad ⇓ \Downarrow ⇓
8 ( 1 0 x − 1 ) g c d ( 8 , L ) = 9 k L g c d ( 8 , L ) {\frac{8(10^x-1)}{gcd(8,L)}} = {\frac{9kL}{gcd(8,L)}} gcd(8,L)8(10x−1)=gcd(8,L)9kL
设 p = 8 g c d ( 8 , L ) , q = 9 L g c d ( 8 , L ) p = {\frac{8}{gcd(8,L)}},q = {\frac{9L}{gcd(8,L)}} p=gcd(8,L)8,q=gcd(8,L)9L
则:
p ∗ ( 1 0 x − 1 ) = q k p*(10^x-1) = qk p∗(10x−1)=qk
由前提: q ∣ ( 1 0 x − 1 ) q|(10^x-1) q∣(10x−1)即:
9 L g c d ( L , 8 ) ∣ ( 1 0 x − 1 ) {\frac{9L}{gcd(L,8)}}|(10^x-1) gcd(L,8)9L∣(10x−1)
\qquad ⇓ \Downarrow ⇓
1 0 x ≡ 1 ( m o d 9 L g c d ( L , 8 ) ) 10^x{\equiv}1{\pmod{\frac{9L}{gcd(L,8)}}} 10x≡1(modgcd(L,8)9L) 同余性质
- 前提:
- 代码
/*
独立思考
*/
#include <math.h>
#include <cstdio>
#include <iostream>
using namespace std;
template <typename T>
void read(T &x)
{
x = 0;
char c = getchar();
int sgn = 1;
while (c < '0' || c > '9') {if (c == '-')sgn = -1; c = getchar();}
while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
x *= sgn;
}
template <typename T>
void out(T x)
{
if (x < 0) {putchar('-'); x = -x;}
if (x >= 10)out(x / 10);
putchar(x % 10 + '0');
}
typedef long long ll;
typedef unsigned long long ull;
ll d, k, p, s, L;
ll phi(ll n) {
ll ans = n;
for (int i = 2; i * i <= n; i++)
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) n /= i;
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
ll gcd(ll x, ll y) {
return y ? gcd(y, x % y) : x;
}
ll ksc(ll a, ll b, ll c) {
ll ans = 0;
while (b) {
if (b & 1) ans = (ans + a) % c;
a = a * 2 % c;
b >>= 1;
}
return ans;
}
ll ksm(ll a, ll b, ll c) {
ll ans = 1 % c;
a %= c;
while (b) {
if (b & 1) ans = ksc(ans, a, c);
a = ksc(a, a, c);
b >>= 1;
}
return ans;
}
ll number() {
d = gcd(L, 8ll);
k = 9 * L / d;
if (gcd(k, 10ll) != 1) return 0;
p = phi(k);
s = sqrt(p);
for (int i = 1; i <= s; i++)
if (p % i == 0 && ksm(10ll, i, k) == 1)
return i;
for (int i = s - 1; i; i--)
if (p % i == 0 && ksm(10ll, p / i, k) == 1)
return p / i;
return 0;
}
int main ()
{
int flag = 0;
while (scanf("%lld", &L) != EOF && L)
{
printf("Case %d: %lld\n", ++flag, number());
}
return 0 ;
}
- 方法
欧拉函数,同余,快速幂 - 总结