P10496 The Luckiest Number 题解
P10496 The Luckiest Number 题解
题目链接
题目大意
给定一个数字 \(L\),求仅由 \(8\) 组成的数字且是 \(L\) 的倍数的正整数中的最小值的位数。
解题思路
对于由 \(x\) 位 \(8\) 组成的数字,可以将其表示为 \(\frac{8}{9}(10^x-1)\),故原题转化为求满足 \(L|\frac{8}{9}(10^x-1)\) 的正整数 \(x\) 的最小值。
设 \(g=\gcd(8,L)\),等式两边同时乘 \(9\) 并除以 \(g\) 得:\(\frac{9L}{g}|(10^x-1)\),由于 \(g\) 的质因数仅有 \(2\)(或者根本没有),所以右边 \(8(10^x-1)\) 除以 \(g\) 后不影响原式结果。
将上式改写为同余式得 \(10^x \equiv 1 (mod\text{ }\frac{9L}{g})\)。因为若 \(a,n\) 互质,满足 \(a^x \equiv 1(mod\text{ }n)\) 的正整数解最小为 \(\phi(n)\) 的约数(证明略),所以可以直接枚举 \(\frac{9L}{g}\) 的约数,每个代入进去尝试即可求出答案。
若 \(\gcd(10,\frac{9L}{g}) \ne 1\),则无解。
复杂度分析
枚举 \(\frac{9L}{g}\) 的因数需要 \(O(\sqrt L)\) 的时间,内层代入尝试需要快速幂优化,所以总体复杂度为 \(O(\sqrt L\log\text{ }L)\)。
代码
// Problem: P10496 The Luckiest Number
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P10496
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// Date: 2025-01-18 12:42:51
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
typedef __int128 ll;
typedef unsigned long long ull;
#define mst(x, y) memset(x, y, sizeof(x))
#define pii pair<ll, ll>
#define fi first
#define se second
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
ll read(){ll x = 0, f = 1;char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9'){x = 10*x+c-'0';c = getchar();}return f*x;}
void writ(ll x){if(x < 0){putchar('-');x = -x;}if(x > 9) writ(x/10);putchar(x%10 | 0x30);return;}
void write(ll x){writ(x);puts("");}
void wr(ll x){writ(x);putchar(' ');}
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll l;
ll gcd(ll x, ll y){
if(x < y) swap(x, y);
if(y == 0) return x;
return gcd(y, x%y);
}
ll phi(ll x){
ll res = x;
for(ll i = 2;i*i <= x;i++){
if(x%i == 0){
res = res/i*(i-1);
while(x%i == 0) x /= i;
}
}
if(x > 1) res = res/x*(x-1);
return res;
}
ll quick_pow(ll x, ll y, ll m){
ll res = 1, bse = x;
while(y){
if(y&1) res = res*bse%m;
bse = bse*bse%m;
y /= 2;
}
return res;
}
void solve(){
for(int i = 1;;i++){
l = read();
if(l == 0) break;
ll g = 9*l/gcd(9*l, 8);
ll p = phi(g), ans = inf;
printf("Case %d: ", i);
if(gcd(10, g) != 1){
write(0);
continue;
}
for(ll j = 1;j*j <= p;j++){
if(p%j) continue;
if(quick_pow(10, j, g) == 1) ans = min(ans, j);
if(quick_pow(10, p/j, g) == 1) ans = min(ans, p/j);
}
if(ans != inf) write(ans);
}
}
signed main(){
solve();
return 0;
}
最后不要忘了双倍经验

浙公网安备 33010602011771号