UVa 11083 Zeroes Revisited

题目描述

所有有经验的参赛者都知道,在阶乘 n!n!n! 中质数 ppp 的出现次数可以用以下公式计算:

f(n,p)=⌊np⌋+⌊np2⌋+⌊np3⌋+⌊np4⌋+⋯f(n,p) = \left\lfloor \frac{n}{p} \right\rfloor + \left\lfloor \frac{n}{p^2} \right\rfloor + \left\lfloor \frac{n}{p^3} \right\rfloor + \left\lfloor \frac{n}{p^4} \right\rfloor + \cdotsf(n,p)=pn+p2n+p3n+p4n+

这个公式可以有效地用于计算任意进制下 n!n!n! 的尾随零的个数。设 z(n,b)z(n,b)z(n,b) 是一个函数,表示在进制 bbbn!n!n! 的尾随零的个数。定义一个新函数 soz(n,b)soz(n,b)soz(n,b) 如下:

soz(n,b)=∑i=1nz(i,b)soz(n,b) = \sum_{i=1}^{n} z(i,b)soz(n,b)=i=1nz(i,b)

给定 nnn 和基数 bbb,你的任务是求出 soz(n,b)soz(n,b)soz(n,b) 的值。

输入限制:

  • 0≤n≤40000000000 \leq n \leq 40000000000n4000000000
  • 1<b≤1000001 < b \leq 1000001<b100000
  • bbb 是无平方因子数(不能被任何平方数整除,除了 111
  • 最多 120012001200 行输入

题目分析

关键观察

  1. 无平方因子数的性质:由于 bbb 是无平方因子数,它的质因数分解形式为 b=p1×p2×⋯×pkb = p_1 \times p_2 \times \cdots \times p_kb=p1×p2××pk,其中每个质因子的指数都是 111

  2. 尾随零的计算:在 bbb 进制下,n!n!n! 的尾随零个数由质因数分解中各个质因子在 n!n!n! 中出现次数的最小值决定:
    z(n,b)=min⁡{f(n,p1),f(n,p2),…,f(n,pk)}z(n,b) = \min\{f(n,p_1), f(n,p_2), \ldots, f(n,p_k)\}z(n,b)=min{f(n,p1),f(n,p2),,f(n,pk)}

  3. 关键优化:对于无平方因子数,尾随零个数实际上由 bbb最大质因子决定。这是因为较大的质因子在阶乘中出现的次数总是小于或等于较小质因子出现的次数:
    z(n,b)=f(n,pmax⁡)其中 pmax⁡ 是 b 的最大质因子z(n,b) = f(n, p_{\max}) \quad \text{其中 } p_{\max} \text{ 是 } b \text{ 的最大质因子}z(n,b)=f(n,pmax)其中 pmax  b 的最大质因子

数学推导

我们需要计算:
soz(n,b)=∑i=1nz(i,b)=∑i=1nf(i,pmax⁡)soz(n,b) = \sum_{i=1}^n z(i,b) = \sum_{i=1}^n f(i, p_{\max})soz(n,b)=i=1nz(i,b)=i=1nf(i,pmax)

展开 f(i,pmax⁡)f(i, p_{\max})f(i,pmax)
soz(n,b)=∑i=1n(⌊ipmax⁡⌋+⌊ipmax⁡2⌋+⌊ipmax⁡3⌋+⋯ )soz(n,b) = \sum_{i=1}^n \left( \left\lfloor \frac{i}{p_{\max}} \right\rfloor + \left\lfloor \frac{i}{p_{\max}^2} \right\rfloor + \left\lfloor \frac{i}{p_{\max}^3} \right\rfloor + \cdots \right)soz(n,b)=i=1n(pmaxi+pmax2i+pmax3i+)

交换求和顺序:
soz(n,b)=∑k=1∞∑i=1n⌊ipmax⁡k⌋soz(n,b) = \sum_{k=1}^{\infty} \sum_{i=1}^n \left\lfloor \frac{i}{p_{\max}^k} \right\rfloorsoz(n,b)=k=1i=1npmaxki

S(n,m)=∑i=1n⌊i/m⌋S(n, m) = \sum_{i=1}^n \lfloor i/m \rfloorS(n,m)=i=1ni/m,则:
soz(n,b)=∑k=1∞S(n,pmax⁡k)soz(n,b) = \sum_{k=1}^{\infty} S(n, p_{\max}^k)soz(n,b)=k=1S(n,pmaxk)

高效计算 S(n,m)S(n, m)S(n,m)

对于 S(n,m)=∑i=1n⌊i/m⌋S(n, m) = \sum_{i=1}^n \lfloor i/m \rfloorS(n,m)=i=1ni/m,我们可以用数学公式直接计算:

q=⌊n/m⌋q = \lfloor n/m \rfloorq=n/m(完整周期的个数),r=n%mr = n \% mr=n%m(最后一个不完整周期的元素个数)。

  • q−1q-1q1 个完整周期:每个周期贡献 0+1+2+⋯+(m−1)=m(m−1)20 + 1 + 2 + \cdots + (m-1) = \frac{m(m-1)}{2}0+1+2++(m1)=2m(m1)
  • 最后一个不完整周期:贡献 q×(r+1)q \times (r + 1)q×(r+1)

因此:
S(n,m)=m×(q−1)q2+q×(r+1)S(n, m) = m \times \frac{(q-1)q}{2} + q \times (r + 1)S(n,m)=m×2(q1)q+q×(r+1)

算法步骤

  1. 寻找最大质因子:对 bbb 进行质因数分解,找到最大的质因子 pmax⁡p_{\max}pmax
  2. 计算总和:对于 k=1,2,3,…k = 1, 2, 3, \ldotsk=1,2,3,,计算 S(n,pmax⁡k)S(n, p_{\max}^k)S(n,pmaxk) 并累加,直到 pmax⁡k>np_{\max}^k > npmaxk>n
  3. 输出结果:对于每个测试用例输出计算得到的 soz(n,b)soz(n,b)soz(n,b)

复杂度分析

  • 寻找最大质因子O(b)O(\sqrt{b})O(b),由于 b≤100000b \leq 100000b100000,这是可接受的
  • 计算总和O(log⁡pmax⁡n)O(\log_{p_{\max}} n)O(logpmaxn),由于 n≤4×109n \leq 4 \times 10^9n4×109,这非常高效
  • 总体复杂度:对于 120012001200 个测试用例,总复杂度是可接受的

代码实现

// Zeroes Revisited
// UVa ID: 11083
// Verdict: Accepted
// Submission Date: 2025-11-19
// UVa Run Time: 0.000s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

// 获取b的最大质因子
ll getMaxPrimeFactor(ll b) {
    ll maxPrime = 1;
    for (ll p = 2; p * p <= b; ++p) {
        if (b % p == 0) {
            maxPrime = max(maxPrime, p);
            while (b % p == 0) b /= p;
        }
    }
    return max(maxPrime, b);
}

// 计算 ∑_{i=1}^n ⌊i/m⌋
ll sumFloor(ll n, ll m) {
    ll quotient = n / m;
    ll remainder = n % m;
    return m * (quotient - 1) * quotient / 2 + quotient * (remainder + 1);
}

// 计算 soz(n, b)
ll soz(ll n, ll b) {
    if (n == 0) return 0;
    ll maxPrime = getMaxPrimeFactor(b);
    ll sum = 0;
    ll power = maxPrime;
    while (power <= n) {
        sum += sumFloor(n, power);
        if (power > n / maxPrime) break;
        power *= maxPrime;
    }
    return sum;
}

int main() {
    ll n, b;
    while (cin >> n >> b && (n || b)) {
        cout << soz(n, b) << endl;
    }
    return 0;
}

总结

本题的关键在于利用无平方因子数的性质和数学推导,将问题转化为计算 ∑i=1nf(i,pmax⁡)\sum_{i=1}^n f(i, p_{\max})i=1nf(i,pmax),然后通过数学公式直接计算,避免了低效的遍历和二分查找。这种数学优化的方法在处理大范围数据时非常有效。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值