【CQOI2007】【BZOJ1257】【洛谷P2261】余数求和(整除分块)

传送门

蒟蒻才开始学整除分块啊

虽然感觉不难

主要是用来求类似于

i=1nki∑_{i=1}^n{\lfloor{ \frac ki }\rfloor}

之类的东西

考虑到对于k(ki1)+1\frac{k}{( \frac {k}{i-1})}+1~k(ki)\frac{k}{(\frac{k}{i})}之间的所有数除上kk的值都不会变

所以我们可以对于每一个这样的部分O(1)O(1)统计答案

考虑到对于i<ni< \sqrt ni>ni>\sqrt n都分别最多只有n\sqrt n种值

所以复杂度为O(n)O(\sqrt n)


对于这道题而言

我们要求的是

i=1nkmod  i∑_{i=1}^nk\mod{i}

i=1nkki∑_{i=1}^n{k-\lfloor \frac k i \rfloor*i}

拆开

nki=1nikin*k-∑_{i=1}^n i{\lfloor \frac k i \rfloor}

后面那项就和整除分块差不多了,等差数列就可以了

代码:

#include<bits/stdc++.h>
using namespace std;
#define gc getchar
#define ll long long
#define int long long
inline int read(){
	int res=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while((isdigit(ch)))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res;
}
#undef gc
ll n,k,ans;
signed main(){
	n=read(),k=read();
	ans=n*k;
	for(int i=1,nxt;i<=n;i=nxt+1){
		if(k/i)nxt=min(k/(k/i),n);
		else nxt=n;
		ans-=(nxt-i+1)*(nxt+i)*(k/i)/2;
	}
	cout<<ans<<'\n';
}

posted @ 2019-01-21 20:03  Stargazer_cykoi  阅读(95)  评论(0编辑  收藏  举报