整除分块

整除分块

计算 ∑ ⌊ 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值