题目链接:P3935 Calculating
题目大意: 若 x x x分解质因数的结果为 x = p 1 k 1 p 2 k 2 . . . p n k n x=p_1^{k_1}p_2^{k_2}...p_n^{k_n} x=p1k1p2k2...pnkn,令 f ( x ) = ( x 1 + 1 ) ( x 2 + 1 ) . . . ( x n + 1 ) f(x)=(x_1+1)(x_2+1)...(x_n+1) f(x)=(x1+1)(x2+1)...(xn+1),求 ∑ i = l r f ( i ) \sum _ { i = l } ^ { r }f(i) ∑i=lrf(i)对 998244353 998244353 998244353取模的结果。其中 x ≤ 1 0 14 x\leq10^{14} x≤1014
题目分析: 其实这道题中的
f
(
x
)
f(x)
f(x) 的值就是
x
x
x的因数个数,所以这道题实际上求的是在
[
l
,
r
]
[l,r]
[l,r] 中
x
x
x 的因数个数的和。 我们首先可以想到的是对于区间
[
l
,
r
]
[l,r]
[l,r] 的答案
a
n
s
ans
ans 实际上是区间
[
1
,
r
]
[1,r]
[1,r] 的答案
a
n
s
1
ans1
ans1 和区间
[
1
,
l
−
1
]
[1,l-1]
[1,l−1] 的答案
a
n
s
2
ans2
ans2 的差。所以,我们现在要求的就是
∑
i
=
1
r
f
(
i
)
\sum_{i=1}^{r}f(i)
∑i=1rf(i) 的值。不难发现,我们要处理的
∑
i
=
1
r
∑
d
∣
i
1
\sum_{i=1}^r \sum_{d|i}1
∑i=1r∑d∣i1 可以写成
∑
d
=
1
r
⌊
n
d
⌋
\sum_{d=1}^r⌊\frac{n}{d}⌋
∑d=1r⌊dn⌋,所以我们只需要处理这个式子即可。对于n/d其实在某些段的值是连续的,这里需要用到分块除法,就是把数值相同的块分成同一组,这样处理后的复杂度变为了
O
(
n
)
O(\sqrt{n})
O(n),可以跑过所有的点。下面是完整代码。
题目代码:
#include<stdio.h>
#include<algorithm>
#define mod 998244353
#define LL long long
using namespace std;
LL n,m,ans1,ans2;
int main()
{
scanf("%lld %lld",&n,&m);
n--;
for(LL l=1,r;l<=n;l=r+1){
r=n/(n/l);//相当于向上取整
ans1=(ans1+(n/l)%mod*(r-l+1)%mod)%mod;
}
for(LL l=1,r;l<=m;l=r+1){
r=m/(m/l);
ans2=(ans2+(r-l+1)%mod*(m/l)%mod)%mod;
}
printf("%lld",(ans2-ans1+mod)%mod);
return 0;
}