版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haut_ykc/article/details/83004760
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
F(n) = (n % 1) + (n % 2) + (n % 3) + ...... (n % n)。其中%表示Mod,也就是余数。
例如F(6) = 6 % 1 + 6 % 2 + 6 % 3 + 6 % 4 + 6 % 5 + 6 % 6 = 0 + 0 + 0 + 2 + 1 + 0 = 3。
给出n,计算F(n), 由于结果很大,输出Mod 1000000007的结果即可。
Input
输入1个数N(2 <= N <= 10^12)。
Output
输出F(n) Mod 1000000007的结果。
Input示例
6
Output示例
3
题解:
n有1e12这么大,肯定不能暴力。
我们考虑将区间分成[1,sqrt(n)]和[sqrt(n),n]这两个区间。
对于第一个区间,我们直接累加答案即可。
对于第二个区间我们发现,由于除数很大,其n/i在很大范围内是一样。
并且在n/i相同的这一区间内其贡献满足等差数列,到这里问题就解决了。
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define mod 1000000007
ll n,ans,last;
ll inv=500000004;//2的逆元
int main(void)
{
scanf("%lld",&n);
ll m=(ll)sqrt(n+0.5);
for(ll i=1;i<=m;i++)
ans=(ans+n%i)%mod;
for(int i=1;i<=m;i++)
{
ll num=((n/i)%mod-n/(i+1)%mod+mod)%mod;
ans=(ans+n%i*num%mod+(num*(num-1)%mod)%mod*inv%mod*i%mod)%mod;
}
if(n/m==m) ans=(ans-(n%m)+mod)%mod;
printf("%lld\n",ans);
return 0;
}