LUOGU P2261 [CQOI2007]余数求和(数论分块)

传送门

解题思路

  数论分块,首先将 \(k\%a\) 变成 \(k-a*\left\lfloor\dfrac{k}{a}\right\rfloor\)形式,那么\(\sum\limits_{i=1}^nk\%i=n*k-\sum\limits_{i=1}^ni*\left\lfloor\dfrac{k}{i}\right\rfloor\),这样的话因为\(\left\lfloor\dfrac{k}{i}\right\rfloor\)的取值只有\(O(\sqrt n)\)级别,所以可以每次找到相等值的左端点和右端点,用一次等差数列求和公式即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring> using namespace std;
typedef long long LL; int n,k;
LL ans; int main(){
scanf("%d%d",&n,&k);ans=(LL)n*k;
for(int l=1,r;l<=n;l=r+1){
if((k/l)!=0) r=min(k/(k/l),n);
else r=n;
ans-=(LL)(k/l)*(r-l+1)*(l+r)/2;
}
cout<<ans;
return 0;
}
上一篇:Extjs学习笔记之九 数据模型(上)-extjs


下一篇:CentOS和AIX查看系统序列号