1.例题
2022年中国高校计算机大赛-团队程序设计天梯赛(GPLT)
对于这道题如果数据范围过大暴力肯定是会超时的
以20为例,一共出现了多少个i的倍数?
可以发现在连续的一段区间内是相同的,那么就启发我们是否可以将其分为若干块分别进行计算呢?
这就是整除分块的核心思想了。
2.整除分块
性质1:当i<=
时,n / i>=
,因为向下取整,所以
=
;如果i>
时,
<=
。
性质2:分块的右端点r=n / (n / i).因为k<=
,那么
,所以对于 i 来说,它所在块的右端点数最大为n / (n / i)。n=21,对于6,n / i=3,n / 3=7,所以6所在块的右端点为7;对于11,21 / 11=1,21 / 1=21,所以11所在块的右端点为21.
有些题目可能有f(i),我们可以用前缀和预处理一下或者用数列求和;对于每一块的 n / i都是相同的,所以我们只需找出左右区间,枚举每一块即可。
复制别人的(不想手写)
void solve(){
int n;
cin>>n;
__int128 r,i=1,sum=n;//区间和会超longlong,int128最大值最高位2^127-1
sum=sum*sum; //不能sum=n*n因为n*n的范围太大
for(i=1;i<=n;i=r+1){
r=n/(n/i); //计算右区间
sum=sum-(r-i+1)*(i+r)/2*(n/i);
//sum%=mod;
}
cout<<(int)(sum%mod);//最后要取模再强转,不然无法输出