洛谷 P3935 Calculating 题解

CSDN同步

原题链接

一看我感觉是个什么很难的式子……

结果读完了才发现本质太简单。

算法一

完全按照那个题目所说的,真的把质因数分解的结果保留。

最后乘。

时间复杂度:(O(r sqrt{r})).

实际得分:(40pts).

(实在想不到比这得分更低的算法了)

算法二

机智的发现是个因数枚举。

然后枚举因数。

时间复杂度: (O(r sqrt{r})).

实际得分: (40pts).

(只是码量少一点)

算法三

推式子。

(f_x) 其实就是 (x) 的因数个数。

我们只需分别求出 (sum_{i=1}^r f_i)(sum_{i=1}^{l-1} f_i) ,再相减即可。

(日常前缀和思路)

[sum_{i=1}^r f_i ]

[= sum_{i=1}^r sum_{j|i} 1 ]

[= sum_{i=1}^r sum_{j=1}^i [j|i] ]

[= sum_{j=1}^r sum_{i=1}^r [j|i] ]

(这步的依据是:我们不枚举每个数的因数,而是考虑每个数作为其它因数所产生的贡献)

[= sum_{j=1}^r lfloor frac{r}{j} floor ]

(这步的依据是:从 (1)(n) 共有 (lfloor frac{r}{j} floor) 个数是 (j) 的倍数)

然后到这里,我们暴力枚举。

时间复杂度: (O(r)).

实际得分:(60pts).

算法四

暴力枚举个头?

答案摆在面前还在那暴力

明明是整除分块好吧。

不知道整除分块是啥?

浅谈整除分块

( exttt{OK}),你发现,这题竟然是 整除分块的模板题

时间复杂度: (O(sqrt{r})).

实际得分:(100pts).

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll MOD=998244353;

inline ll read(){char ch=getchar();ll f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
	ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}

int main(){
	ll l=read(),r=read();
	ll ans=0; l--;
	for(ll i=1,t;i<=r;i=t+1) {
		t=r/(r/i); ll len=(t-i+1)%MOD;
		ans=(ans+len*(r/i)%MOD)%MOD;
	} //这是 1~r 的
	for(ll i=1,t;i<=l;i=t+1) {
		t=l/(l/i); ll len=(t-i+1)%MOD;
		ans=(ans-len*(l/i)%MOD+MOD)%MOD; //这是 1~(l-1) 的
                //为了防止模出负数,我们加上 MOD 再模
	} printf("%lld
",(ans+MOD)%MOD);
	return 0;
}

原文地址:https://www.cnblogs.com/bifanwen/p/12530283.html