整除分块(知识+例题)

1.例题

2022年中国高校计算机大赛-团队程序设计天梯赛(GPLT)

对于这道题如果数据范围过大暴力肯定是会超时的

以20为例,一共出现了多少个i的倍数?

可以发现在连续的一段区间内是相同的,那么就启发我们是否可以将其分为若干块分别进行计算呢?

这就是整除分块的核心思想了。

2.整除分块

性质1:当i<=\left \lfloor \sqrt{n} \right \rfloor时,n / i>= \sqrt{n},因为向下取整,所以\left \lfloor \frac{n}{i} \right \rfloor=\sqrt{n};如果i>\left \lfloor \sqrt{n} \right \rfloor时,\left \lfloor \frac{n}{i} \right \rfloor<=\sqrt{n}

性质2:分块的右端点r=n / (n / i).因为k<=\frac{n}{i},那么\frac{n}{k}>=\frac{n}{\frac{n}{i}},所以对于 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);//最后要取模再强转,不然无法输出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值