Description
求
Input
两个整数n和k(1<=n,k<=1e9)
Output
输出
Sample Input
5 3
Sample Output
7
Solution
暴力显然超时,n超过k的部分可以用(n-k)*k得到,所以只要解决[1,k]这个区间即可,首先我们知道当k/i相同时,k%i是公差为k/i的等差数列,那么我们可以从sqrt(k)到2枚举k/i,那么我们就得到了(sqrt(k),n]这个区间上的答案,而求解[1,sqrt(k)]这个区间可以在O(sqrt(k))的时间内解决,这个时间复杂度显然可行
Code
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll solve(ll n,ll k)
{
ll p=(ll)sqrt(1.0*k),q=k/p,ans=0;
if(n>k)ans+=(n-k)*k;//大于k的部分
for(ll i=p;i>1;i--)
{
ll s=k/i,e=k/(i-1);
if(s>n)break;//s大于n则退出循环
if(e>n)e=n;//e于n则令其为n只求s~n这一段
ans+=(k%(s+1)+k%e)*(e-s)/2;//等差数列求和公式
}
for(ll i=1;i<=n&&i<=q;i++)//求[1,sqrt(k)]部分
ans+=k%i;
return ans;
}
int main()
{
ll n,k;
while(~scanf("%lld%lld",&n,&k))
printf("%lld",solve(n,k));
return 0;
}