题意:
给定n和k,求一个最大的x,使得n! % k ^ x == 0
思路:
打出素数表,用每个素数分解n!和k,得到y和x,ans = min(ans,y/x)
对m!阶乘唯一分解可以写作:
while (m) {
m /=prime[i];
y += m;
}
类似于统计m以内有多少个prime[i]的倍数
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1e7 + 10; const ll INF = 1e18; bool isprime[maxn]; int pcnt, prime[maxn]; void creat_prime() { memset(isprime, true, sizeof(isprime)); isprime[0] = isprime[1] = false; pcnt = 0; for (int i = 2; i < maxn; i++) { if (isprime[i]) prime[++pcnt] = i; for (int j = 1; j <= pcnt && prime[j] * i < maxn; j++) { isprime[prime[j]*i] = false; } } } int main() { creat_prime(); int T; ll k, n; scanf("%d", &T); for (int kase = 1; kase <= T; kase++) { scanf("%lld%lld", &n, &k); printf("Case %d: ", kase); if (k == 1) { printf("inf\n"); continue; } ll ans = INF; for (int i = 1; i <= pcnt; i++) { if (prime[i] > k) break; ll x = 0, y = 0, m = n; while (k % prime[i] == 0) { x++; k /= prime[i]; } if (!x) continue; while (m) { m /= prime[i]; y += m; } ans = min(ans, y / x); } if (k > 1) { ll y = 0, m = n; while (m) { m /= k; y += m; } ans = min(ans, y); } printf("%lld\n", ans); } return 0; }