题目大意: 若 x x x 可以分解成 p 1 k 1 p 2 k 2 p 3 k 3 . . . p s k s p_1^{k_1}p_2^{k_2}p_3^{k_3}...p_s^{k_s} p1k1p2k2p3k3...psks,那么 f ( x ) = ( k 1 + 1 ) ( k 2 + 1 ) . . . ( k s + 1 ) f(x)=(k_1+1)(k_2+1)...(k_s+1) f(x)=(k1+1)(k2+1)...(ks+1),求出 ∑ i = l r f ( i ) \sum_{i=l}^r f(i) ∑i=lrf(i)
前置知识——因数个数定理
描述: 将一个数 x x x 质因数分解后,可以表示为 x = p 1 c 1 p 2 c 2 . . . p k c k x=p_1^{c_1}p_2^{c_2}...p_k^{c_k} x=p1c1p2c2...pkck,那么 x x x 的因数个数就是 ∏ i = 1 k ( c i + 1 ) \prod\limits_{i=1}^k(c_i+1) i=1∏k(ci+1)。
证明: 由于 x x x 的每个因子也可以表示上面的形式,只不过 c c c 的值不同,设因子的质因数分解后为 p 1 c 1 ′ p 2 c 2 ′ . . . p k c k ′ p_1^{c_1'}p_2^{c_2'}...p_k^{c_k'} p1c1′p2c2′...pkck′,对于 c i ′ c_i' ci′,它的取值范围是 0 0 0 ~ c i c_i ci,即有 ( c i + 1 ) (c_i+1) (ci+1) 种取值方案,所以总因子个数就是 ∏ i = 1 k ( c i + 1 ) \prod\limits_{i=1}^k(c_i+1) i=1∏k(ci+1)。
题解
发现题目定义的 f ( i ) f(i) f(i) 其实就是 i i i 的因数个数。
那么考虑换一个角度,统计每一个因数 x x x 会被多少个 i i i 计算到。
显然, x x x 的每个倍数都会将 x x x 计算一次,将询问差分一下,变成 ∑ i = 1 r f ( i ) − ∑ i = 1 l − 1 f ( i ) \sum_{i=1}^rf(i)-\sum_{i=1}^{l-1}f(i) ∑i=1rf(i)−∑i=1l−1f(i),那么问题就变成了求 1 1 1 ~ n n n 范围内有多少个 x x x 的倍数,即
求 ∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^n \lfloor \frac n i \rfloor ∑i=1n⌊in⌋
然而这是个除法分块的模板。
代码如下:
#include <cstdio>
#include <cstring>
#define mod 998244353ll
#define ll long long
ll a,b;
ll solve(ll x)
{
ll l=1,r,re=0;
while(l<=x)
{
r=x/(x/l);
re=(re+(r-l+1)*(x/l)%mod)%mod;
l=r+1;
}
return re;
}
int main()
{
scanf("%lld %lld",&a,&b);
printf("%lld",(solve(b)-solve(a-1)+mod)%mod);
}