CF1114C Trailing Loves (or L'oeufs?)
题目大意:
给定(n),求(n!)在(b)进制下末尾(0)的个数。
思路:
我们以十进制来举例子。
进制数(10 = 2 imes 5)
比如说一个十进制数(20),末尾有一个(0),将(20)质因数分解为(20 = 2^{2} imes 5)
十进制(100),末尾有两个(0),将其质因数分解为(100 = 2^{2} imes 5^{2})
十进制数(1000),末尾有三个(0),将其质因数分解为(1000 = 2^{3} imes 5^{3})
……
不难发现其规律。
设进制数(b) (=) (p_1^{r_1})( imes)(p_2^{r_2})( imes)…( imes)(p_k^{r_k}),质数(p_1),(p_2),…,(p_k)在(n!)中的次数分别为(cnt_1),(cnt_2),…,(cnt_k),答案为(min(⌊frac{cnt_1}{p_1}⌋,⌊frac{cnt_2}{p_2}⌋…⌊frac{cnt_k}{p_k}⌋))
对于求(n!)中每一个质数出现的次数,我们再举一个例子。
比如(5!)中质数(2)的出现次数:
(5 / 2 = 2)
(2 / 2 = 1)
(1 / 2 = 0)
你会发现将等式右边的数求和正好是(2)的出现次数。
Formally,对于质数(p),其在(n!)中的出现次数为:(sum_{i=1}^{r}{lfloor {frac{n}{p^i}} floor}(p^r le n , p^{r+1} > n))
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 10010;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct Prime {
LL num, tot;
}p[N];
LL cnt;
void pff(LL x) { //分解质因数
for (LL i = 2; i * i <= x; i++) {
while (x % i == 0) {
x /= i;
if (p[cnt].num == i) p[cnt].tot++;
else p[++cnt].num = i, p[cnt].tot = 1;
}
}
if (x > 1) {
if (p[cnt].num == x) p[cnt].tot++;
else p[++cnt].num = x, p[cnt].tot = 1;
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
LL n, b; cin >> n >> b;
pff(b);
LL ans = INF;
for (int i = 1; i <= cnt; i++) {
LL mul = 1, now = 0;
while (n / mul >= p[i].num) {
mul *= p[i].num;
now += n / mul;
}
ans = min(ans, now / p[i].tot);
}
cout << ans << endl;
return 0;
}