codeforces 616E - Sum of Remainders

本文介绍了一种计算n模1到n模m之和的有效算法,通过将问题转化为求等差数列的和来减少计算复杂度。文章提供了一个具体的C++实现示例,并讨论了如何利用开方策略优化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:计算 n mod 1+n mod 2 + ... n mod m 


思路:其实计算 n mod x 可以转换为   n - [n/x]*x  n/x=i 是一个连续的范围 比如 10/4 =2 10/5=2  我们只要计算出 n/x=i 的一个范围 ,就可以用等差公式求和了 


ps :上网查了一下 有开方的策略 好像才是正确姿势 = = 代码太丑 爆了好多次LL 

#include<cstring>
#include<cstdlib>
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100010
#define MOD 1000000007
#define LL long long

LL n,m,ans;

LL divide2(LL x,LL y)
{
    if(x%2==0)
        return (((x/2)%MOD)*(y%MOD))%MOD;
    else
        return ((x%MOD)*((y/2)%MOD))%MOD;
}

int main()
{
    scanf("%lld%lld",&n,&m);
    ans=((max(0LL,m-n)%MOD)*(n%MOD)%MOD+MOD)%MOD;
    for(LL i=n,j=1,k=1,l=1;i>0;l+=k)
    {
        ans=((ans+(n%MOD)*(k%MOD)-(i%MOD)*divide2(k+j-1+j,k)%MOD)%MOD+MOD)%MOD;
        if(l>=m)break;
        i=min(i-1,n/(k+j));
        j=k+j;
        if(i==0)break;
        k=min(n/i-j+1,m-j+1);
    }
/*
    LL ans2=0;
    for(LL i=1;i<=m;i++)
        ans2=(ans2+n%i)%MOD;
*/
    printf("%lld\n",ans);
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值