欧拉定理
简单说就是,如果和为正整数,且互为质数也就是,那么:
该式表示与1在模下同余,即,其中为欧拉函数。
欧拉函数
表示小于等于的所有正整数中与互素的数的个数。显然如果我们的复杂度去遍历求解欧拉函数是不行的,它有一个更快的公式:
如果,其中为质数,该式对于表示的是质因数分解,那么:
简单证明一下,记以内某个质数的倍数的集合为,目标就是找到它们的并集的大小,并将减去,就是。
根据集合论,其实,奇数相加、偶数相减。
如何找到的循环节?
考虑。
- 如果的因子仅含有2或5,那么该小数是循环小数;
- 如果不含2或5,10与互素,根据欧拉定理,,其中便是循环节,但不一定是最小的,因为最小的循环节重复k遍仍是循环节,所以通过遍历的因子找到最小的循环节即可。
- 如果除了2和5还有其他的,先找出2和5的个数分别为a与b,循环节前面一段的长度便是,剩下的10与互素,找到最小循环节即可。
import math
def phi(x: int) -> int:
ans, i = x, 2
while i * i <= x:
if x % i == 0:
ans = ans // i * (i - 1)
while x % i == 0: x //= i
i += 1
if x > 1: ans = ans // x * (x - 1)
return ans
p, q = map(int, input().split())
g = math.gcd(p, q)
p //= g
q //= g # 化简
c2, c5 = 0, 0
while q % 2 == 0:
q //= 2
c2 += 1
while q % 5 == 0:
q //= 5
c5 += 1
if q == 1:
print(-1)
exit(0)
phiq = phi(q) # 拿到欧拉函数的值
ans, i = phiq, 2 # 找到最小的循环节
while i * i <= phiq:
if phiq % i == 0: # 是因子
if pow(10, i, q) == 1: ans = min(ans, i)
if pow(10, phiq // i, q) == 1: ans = min(ans, phiq // i)
i += 1
print(max(c2, c5), ans)
PS:涉及大整数的乘法、求模还是用python吧,用C++开到__int128
才行。