bzoj1257

给出n,k

n>=k都可以直接算的。

那么仅考虑n<k的情况

因为k%i= k-(k/i)*i (取整)

所以,对于多个i值,k/i的结果是一样,所以把这些数放在一起算

k-(k/i1)*i1     k-(k/i2)*i2    k*(k/i3)*i3这些数构成一个等差数列(i逐渐递增)

所以我们可以一次性过掉多个i,而具体过掉多少i,用二分来查找

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
long long n,k,ans=0,now=1,G;
long long findlast(long long l,long long r)
{
 if (l==r)return l;
 long long mid=l+r>>1;
 mid+=1; 
 if (k/mid==G)return findlast(mid,r);
 else return findlast(l,mid-1); 
}
int main()
{   
 scanf("%lld%lld",&n,&k);
 if (n>k){ans+=(n-k)*k;n=k;}
 while(now<=n)
 {
  G=k/now;
  long long last=findlast(now,n);
  ans=ans+(k*2-G*(now+last))*(last-now+1)/2;
  now=last+1;
 }
 printf("%lld\n",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值