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; 
}

最后不要忘了双倍经验

posted @ 2025-01-21 07:58  Hirasawayuiii  阅读(43)  评论(0)    收藏  举报