一看我感覺是個什麼很難的式子……
結果讀完了才發現本質太簡單。
算法一
完全按照那個題目所說的,真的把質因數分解的結果保留。
最後乘。
時間複雜度:.
實際得分:.
(實在想不到比這得分更低的算法了)
算法二
機智的發現是個因數枚舉。
然後枚舉因數。
時間複雜度: .
實際得分: .
(只是碼量少一點)
算法三
推式子。
其實就是 的因數個數。
我們只需分別求出 和 ,再相減即可。
(日常前綴和思路)
(這步的依據是:我們不枚舉每個數的因數,而是考慮每個數作爲其它因數所產生的貢獻)
(這步的依據是:從 到 共有 個數是 的倍數)
然後到這裏,我們暴力枚舉。
時間複雜度: .
實際得分:.
算法四
暴力枚舉個頭?
答案擺在面前還在那暴力
明明是整除分塊好吧。
不知道整除分塊是啥?
,你發現,這題竟然是 整除分塊的模板題 。
時間複雜度: .
實際得分:.
#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\n",(ans+MOD)%MOD);
return 0;
}