题意:求所有满足条件的三元组的数量
解题思路:因为要满足a=b=c,所以易得c⩽b⩽a,优先固定a,所以我们要求∑b=1a{a×b}
不好算是吧!我们用补集转化对这个式子进行一个变形:∑b=1a{∀b}−∑b=1a{a∣b}
所以我们现在求a的所有因子就行了,而范围内有多少个值呢
由整除原理N÷a=c时,a×c⩽N,所以可得c⩽⌊aN⌋,我们又将问题转化到了求∑a=1N⌊aN⌋的个数上,大家用代码跑个实验找找每个⌊aN⌋的规律
可以发现很多重复的值对不对,仔细数一下,不同的数的个数最多只有n个
这个时候就要祭出我们的大杀招:数论分块了
我们对所有的c⩽⌊aN⌋的可能分块,就可以避免对相同值的重复多次计算
在思考一下分块的方法,首先最后会更新为l=r+1是不必多说的,那么r的位置在哪里呢
回看一下我们的目的:寻找最大的r满足⌊lN⌋=⌊rN⌋,因为是找最大的r,所以可以丢掉下取整写为⌊lN⌋=rN
所以r=⌊⌊lN⌋N⌋(出题人想出这玩意家里得请哈基高了),然后跑循环迭代更新就能求得最大值了
AC代码
Details
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
const int inv=( mod+1 )/2;
int main() {
std::ios::sync_with_stdio( false );
std::cin.tie( nullptr );
ll n;
cin>>n;
ll p1=( n%mod )*( ( n+1 )%mod )%mod*inv%mod;
ll p2=0;
for( ll l=1,r;l<=n;l=r+1 )
{
r=n/( n/l );
ll len=( r-l+1 )%mod;
ll val=( n/l )%mod;
p2=( p2+len*val%mod )%mod;
}
cout<<( p1-p2+mod )%mod;
return 0;
}
时间复杂度:O(n)