#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,k,l,r,right;
scanf("%d %d",&n,&k);
long long ans = (long long)n * k;
for (int i = 1 ; i <= n ; i = right + 1)
{
l = i; r = n ; int mid;
int a = k/i;
while (l <= r)
{
mid = (l+r) / 2;
if (k/mid == a)
{
right = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
long long cha = (long long)a * (i+right)*(right-i+1)/2;
ans -= cha;
}
cout<<ans<<endl;
return 0;
}
这道题的我的思路:(我很弱的,各位大佬多多指导——特别是Srf红名大神)
易证得:(刘翔的名言)
ans = ∑ i = 1 to n (k mod i)
则 ans = ∑ i = 1 to n (k - [k/i]*i) 做过高精度取余的大佬们必定知道
所以 ans = n * k - ∑ i = 1 to n ([k/i]*i)
注意到:[k/i]当k一定时,大约只有√k种取值 。 所以 我们可以用二分的方式找到一组 L 和 R , 使得L和R中任意一个i,满足[k/i]相等,这样就不会超时了!
December 31st:
在此特别感谢Srf大佬的指导(帮助小蒟蒻在0ms的时间内AK了!)膜拜大佬!!
思路:如果一段区间L和R满足[k/i]相等,那么下一段同样满足此条件的区间为:[R+1,min(k/(k/i),n)](当k/i != 0时) (注意:这里的min(…)很重要,因为k有可能 > n,不加上会多减掉一部分(即n+1到k/(k/i)))当 k/i == 0时,太弱智了,自己想吧。。。
0ms AK 的代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n,k,l;
scanf("%lld %lld",&n,&k);
long long ans = n * k;
for (long long i = 1 ; i <= n ; i = l + 1)
{
long long a = k/i;
l = (a != 0) ? min(k/a,n) : n;
long long cha = a * (i+l)*(l-i+1)/2;
ans -= cha;
}
cout<<ans<<endl;
return 0;
}