Description
给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7
Input
输入仅一行,包含两个整数n, k。
Output
输出仅一行,即j(n, k)。
Sample Input
5 3
Sample Output
7
HINT
50%的数据满足:1<=n, k<=1000 100%的数据满足:1<=n ,k<=10^9
题解
用了一个看起来比较奇怪的方法
首先x % i = x – (int)(x / i) * i,这个很好YY吧
然后可以找出每个(int)(x / i)相等的一段用等差数列求和来做。
可以证明最多分成sqrt(n)段
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#define ll long long
int n,k;
using namespace std;
int findl(int x)
{
int l=0,r=n;
while (l!=r)
{
int mid=(l+r+1)/2;
if (k/mid>x) l=mid;else r=mid-1;
}
return l+1;
}
int findr(int x)
{
int l=0,r=n;
while (l!=r)
{
int mid=(l+r+1)/2;
if (k/mid<x) r=mid-1;else l=mid;
}
return l;
}
int main()
{
cin>>n>>k;
ll ans=0;
int l,r;
for (int i=1;i<=n;i=r+1)
{
l=findl(k/i),r=findr(k/i);
ll d=k/i,len=r-l+1;
ans+=len*(k%l)-len*(len-1)*d/2;
}
cout<<ans;
}