Codeforces 616E Sum of Remainders(数论)(模运算)(*2200)

本文探讨了在面对大规模数据处理时,如何通过优化模运算来提高算法效率。通过对模运算本质的理解,采用了一种新的表达方式,将传统的%运算转换为更高效的计算方法。通过实例解析,展示了在解决具体问题时,如何利用这一技巧来避免暴力计算,实现快速求解。

http://codeforces.com/problemset/problem/616/E

刷题真的是一个积累知识点的过程,如果不刷这道题,永远都想不到应该是把%运算换一种表达形式进行计算

题意:对于给定n,m求sum,sum = n % 1 + n % 2 + ... + n % m

由于数据过大,1e13,所以暴力肯定不可取,解题思路是回归到模运算的本质上去

*a % b = a - b*(a/b)

题解链接,博客里讲得很清楚,这里就不赘述了,数论对公式的推导真的很严格,而且如果是我知道了思路之后,也一定会第一时间定义两个变量模拟l和r,然而博主只用了一个变量r,这种问题真的是先想明白了再做的好啊,能省去大把大把的时间

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
#define ll long long
using namespace std;

int main()
{
    ll n, m;
    ll r;
    cin>>n>>m;
    ll ans1 = ((n%mod)*(m%mod))%mod;
    m = min(n, m);//n/i,大于n的部分等于零无意义不用求
    ll ans = 0;
    //i模拟左边界,r模拟右边界
    for(ll i = 1; i <= m; i ++)
    {
        r = min(n/(n/i), m);
        //cout<<r<<endl;
        ll a = i + r;
        ll b = r - i + 1;
        if(a%2) b/=2;
        else a/=2;
        ans = (ans + ((a%mod)*(b%mod)%mod)*(n/i)%mod)%mod;//等差数列求和
        i = r;//执行完此次for循环自动加一
    }
    cout<<(ans1 - ans + mod) % mod<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值