P10496 The Luckiest Number 题解

P10496 The Luckiest Number 题解

题目链接

题目大意

给定一个数字 L,求仅由 8 组成的数字且是 L 的倍数的正整数中的最小值的位数。

解题思路

对于由 x8 组成的数字,可以将其表示为 89(10x1),故原题转化为求满足 L|89(10x1) 的正整数 x 的最小值。

g=gcd(8,L),等式两边同时乘 9 并除以 g 得:9Lg|(10x1),由于 g 的质因数仅有 2(或者根本没有),所以右边 8(10x1) 除以 g 后不影响原式结果。

将上式改写为同余式得 10x1(mod 9Lg)。因为若 a,n 互质,满足 ax1(mod n) 的正整数解最小为 ϕ(n) 的约数(证明略),所以可以直接枚举 9Lg 的约数,每个代入进去尝试即可求出答案。

gcd(10,9Lg)1,则无解。

复杂度分析

枚举 9Lg 的因数需要 O(L) 的时间,内层代入尝试需要快速幂优化,所以总体复杂度为 O(Llog 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; 
}

最后不要忘了双倍经验

本文作者:HirasawaYuii

本文链接:https://www.cnblogs.com/HirasawaYuii/p/18682808

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Hirasawayuiii  阅读(13)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起