当前位置: 代码迷 >> 综合 >> 【CodeForces】【数学】616E-Sum of Remainders
  详细解决方案

【CodeForces】【数学】616E-Sum of Remainders

热度:52   发布时间:2023-11-21 07:11:08.0

CodeForces 616E Sum of Remainders

题目

◇题目传送门◆

题目大意

给定n,mn,mmi=1(nmodi)∑i=1m(nmodi)

思路

暴力???10131013,早就炸了。。。

我们就用数学方法分析一下:

Step1.变模为求和

众所周知,nmodinmodi是与n?i??ni?n?i??ni?等价的,不信可以找几个数算一算。

S=mi=1(nmodi)S=∑i=1m(nmodi),不难推出S=n?m?mi=1i??ni?S=n?m?∑i=1mi??ni?。所以,我们成功地将模运算转化为了求和运算。

Step2.10131013

n?mn?m的计算对于我们来说是极其容易的,难点就是后面的那个mi=1i??ni?∑i=1mi??ni?

作为一个在数学世界里搞了N年事情的大佬,经验能够告诉我:?ni??ni?的结果有些是一样的,于是区间[1,m][1,m]就被分成了许多个具有不同?ni??ni?的值所构成的区间。

不明白?举个例子:令n=18n=18

很容易发现,区间[1,18][1,18]被分为了[1,1],[2,2],[3,3],[4,4],[5,6],[7,9],[10,18][1,1],[2,2],[3,3],[4,4],[5,6],[7,9],[10,18]七个区间,而这七个区间都可以使用等差数列求出和。

Step3.计算区间??

我们容易发现,每个区间的开始就是上一个区间的结束+1 (废话)

我们设区间ii的开头为 l i ,结尾为riri,不难得出递推式:

li=ri?1+1ri=n?ni?li=ri?1+1ri=n?ni?

边界条件就是 l1=1,r1=1l1=1,r1=1

Step4.计算答案

终于到了激动人心的时刻了!

我们由上面三步可得,区间[li,ri][li,ri]是一个等差数列,所以对于这个区间,答案应减去:

xi?(ri?li+1)?(li+ri)2xi?(ri?li+1)?(li+ri)2

其中 xi=nixi=ni

实现细节

注意应边模边计算。

正解代码

#include<cstdio>
#include<algorithm>
using namespace std;typedef long long ll;
const int Mod=1e9+7;ll N,M;ll GetSum(ll x) {
   //等差数列return (x%Mod)*((x+1)%Mod)/2%Mod;
}
ll Sum(ll l,ll r) {return GetSum(j)-GetSum(i-1);
}ll ModAdd(ll x,ll y) {return (x%Mod+y%Mod)%Mod;
}
void ModSub(ll &ans,ll i,ll j,ll x) {ans=ModAdd(ans,Mod-Sum(j,i-1)*x%Mod);
}int main() { #ifdef LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifscanf("%lld %lld",&N,&M);ll ans=(N%Mod)*(M%Mod)%Mod;M=min(N,M);//当N>i时,x=0,不需要再算for(ll i=1,j,x;i<=M;i=j+1) {x=N/i;j=min(N/max(x,1*1LL),M);ModSub(ans,i,j,x);}printf("%lld\n",ans);return 0;
}