整除分块
计算 ∑ ⌊ n / i ⌋
直接O(n)可解
但是有许多⌊ n / i ⌋ 的值是一样的,且值相同的连续
每一段相同的数,最后一位的位置为n/(n/i)
有这个结论之后就可以O(√n)计算了
code:
int ans=0;
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
bzoj1257 余数之和
题意:
给n和k,求k%1+k%2+.....k%n
思路:
k%i可以转化成 k-(k/i)*i
这也的话整个式子就变成n*k+∑(⌊ k / i ⌋ *i) ; (1<=i<=n)
我们知道⌊ k / i ⌋分段相同,但是⌊ k / i ⌋ *i后面的i是会变的
设某一段的k/i=t (这一段的k/i相同),这一段的区间为[l,r]
则这一段的为t*l+t*(l+1)...+t*r
->t*(l+(l+1)...+r)
l+(l+1)....+r可以用公式r*(r+1)/2-(l-1)*l/2计算
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int n,k;
while(cin>>n>>k){
int ans=n*k;
for(int l=1,r;l<=n;l=r+1){
if(k/l)r=min(n,k/(k/l));//l<=k的情况
else r=n;//l>k的情况(大于k的时候k%i=k,也可以把这种情况提出去单独计算)
int ll=(l-1)*l/2;
int rr=r*(r+1)/2;
ans-=(k/l)*(rr-ll);//rr-ll是(l+(l+1)...+r)
}
cout<<ans<<endl;
}
return 0;
}