Wraith_Fiee的博客

P2261 [CQOI2007]余数求和

2021-11-21 · 3 min read
整除分块

原题传送门

题目大意:给出正整数nn,kk,请计算G(n,k)=i=1n k mod iG(n,k)=\sum_{i=1}^n\ k\ mod\ i
思路:一道整除分块的入门题


整除分块的基本形式为:i=1nni\sum_{i=1}^n\lfloor \frac{n}{i}\rfloor
对于任意一个i(in)i(i\le n),我们要找到一个最大的j(ijn)j(i\le j\le n),使得ni=nj\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor,那么此时j=nnij=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor

显然ijni\le j\le n(证明从略),设k=nik=\lfloor\frac{n}{i}\rfloor,当nj=k\lfloor\frac{n}{j}\rfloor=kjmax=nkj_{max}=\lfloor\frac{n}{k}\rfloor(证明从略)

那么对于每次以[i,j][i,j]为一块,分块求和即可

Code:

for(ll l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ans+=(r-l+1)*(n/l);
}

对于本题来说,i=1n k mod i=i=1n kiki=nki=1n iki\sum_{i=1}^n\ k\ mod\ i=\sum_{i=1}^n\ k-i*\lfloor\frac{k}{i}\rfloor=n*k-\sum_{i=1}^n\ i*\lfloor\frac{k}{i}\rfloor

对于i=1n iki\sum_{i=1}^n\ i*\lfloor\frac{k}{i}\rfloor,我们把每块[l,r][l,r]对应的i=lr iki\sum_{i=l}^r\ i*\lfloor\frac{k}{i}\rfloor中,令T=i=lrkiT=\sum_{i=l}^r\lfloor\frac{k}{i}\rfloori=lr iki=Ti=lr i=Tl+r2\sum_{i=l}^r\ i*\lfloor\frac{k}{i}\rfloor=T*\sum_{i=l}^r\ i=T*\frac{l+r}{2}

复杂度O(n)O(\sqrt n)

Code:

#include <bits/stdc++.h>
using namespace std;
const int N=2e3+10,mod=1e9+7;
typedef long long ll;
ll n,k;
int main(){
	cin>>n>>k;
	ll ans=n*k;
	for(ll l=1,r;l<=n;l=r+1){
		if(k/l!=0) r=min(n,k/(k/l));
		else r=n;
		ans-=(l+r)*(k/l)*(r-l+1)/2;
	}
	cout<<ans<<endl;
	return 0;
}
 
在吹不出褶皱的日子里发光
Powered by Gridea