河南萌新联赛2025第(四)场 B ----0!!!!!

题目链接: https://ac.nowcoder.com/acm/contest/115184/B
蒟蒻第一次写题解


♠题面

给定两个整数 LR (LR),求区间 [L , R] 中所有整数的因数乘积末尾的零的个数。(1≤L≤R≤\(10^{10}\))

♣思路

数论分块

首先,\(F_p(n)\)为在区间[1 , n]中 ,所有整数的 “因数乘积” 里,能被 \(p^x\) 整除的最大非负整数 x 。
即把把 1 到 n 每个数的因数全部乘起来,这个巨大乘积中,最多包含多少个 p 的因子(即最大的 x ,让 \(p^x\) 能整除这个乘积 )
由于需要求的是因数乘积末尾的 0 的个数,所以这个个数与因子 25 的个数有关,只需要统计区间内因子 25 的个数,取其最小值即可。
即min{\(F_2(R)\) - \(F_2(L-1)\)\(F_5(R)\) - \(F_5(L-1)\)}
回到\(F_p(n)\),我们可以得到

\[F_p(n)=\sum_{i = 1}^n\sum_{d|i}\sum_{k = 1}^{[p^k|d]} [p^k|d] \]

  • \([p^k|d]\)是一个指示函数,如果d可以整除\(p^k\),该表达式结果为1,否则为0。以d=12,p=2为例,k=1和k=2时,\(p^k\)=2,4,可以被d整除,结果为1,当k=3的时候\(p^k\)=8,不能被d整除,所以12中包含2个2因子。\(\sum_{k = 1}^{[p^k|d]} [p^k|d]\)这个式子得出来的结果就是d中包含的p的因子的个数
  • \(\sum_{d|i}\)则表示所有i的因子(d)中p因子的个数
  • \(\sum_{i = 1}^n\)同理表示1n之间的数
  • \(F_p(n)=\sum_{i = 1}^n\sum_{d|i}\sum_{k = 1}^{[p^k|d]} [p^k|d]\)即是区间[1 , n]中,所有整数的因数乘积里,能被 \(p^x\) 整除的最大非负整数 x

接下来交换求和次序,将k提前

\[F_p(n)=\sum_{k = 1}^n\sum_{i = 1}^n\sum_{d|i} [p^k|d] \]

  • 这是调整计算顺序,从 “先数、再因数、再看 \(p^k\) ”,变成 “先定 \(p^k\) ,再找含它的数和因数” 。

然后更换一下枚举对象,从枚举数到枚举约数

\[F_p(n) = \sum_{k=1}^n \sum_{\substack{d=1 \\ p^k \mid d}}^n \left\lfloor \frac{n}{d} \right\rfloor \]

  • 由于d是\(p^k\)的倍数,而i是d的倍数。统计有多少个i能够整除d,即\(\left\lfloor \frac{n}{d} \right\rfloor\)
  • 这一步把 “数 i 及其因数 d ” 的关系,转化成 “直接找含 \(p^k\) 的 d ,再算倍数个数”

简化式子,同除\(p^k\)

\[F_p(n)=\sum_{k = 1}^{\lfloor \frac{n}{p^k} \rfloor}\sum_{d = 1}^{\lfloor \frac{n}{p^k} \rfloor} \lfloor \frac{n}{p^k \cdot d} \rfloor \]

  • 因为 d 是 \(p^k\) 的倍数,设 \(d = p^k \cdot t\)(t 是正整数 )

接下来对k进行枚举,内层进行数论分块就可以得到结果。

♥Code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using ldb = long double;
#define all(x) (x).begin(), (x).end()

i64 Fp(i64 x, i64 nn)
{
    i64 num = 0;
    for (i64 i = x; i <= nn; i *= x)
    {
        i64 n = nn / i;
        for (i64 l = 1; l <= n; l = n / (n / l) + 1)
        {
            i64 r = n / (n / l);
            num += (r - l + 1) * (n / l);
        }
    }
    return num;
}

void solve()
{
    i64 L, R;
    cin >> L >> R;
    i64 a = Fp(2, R) - Fp(2, L - 1);
    i64 b = Fp(5, R) - Fp(5, L - 1);
    cout << min(a, b) << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    i64 t = 1;
    //cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

没了qwq
bq

posted @ 2025-08-06 20:50  FWFWFW11  阅读(46)  评论(0)    收藏  举报