1257: [CQOI2007]余数之和sum
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 2787 Solved: 1278
[ Submit][ Status][ Discuss]
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
重庆oi的题,因为所给的数据很大,到了20亿,循环肯定是不行的,想到余数出现的等差数列规律,通过计算到sqrt(n),就行了:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
ll m,n,p,j,k,l,ans,help;
/*void ac(ll m,ll n)//类似二分
{
k=sqrt(n);
for(ll i=1;i<=k;i++)
ans+=n%i;
for(ll i=1;i<=k;i++)
{
l=n/(i+1);
l+=1;
if(m>l)
ans+=(n%l+n%m)*(m-l+1)/2;
if(l==k)
break;
ans+=n%l;
m=n/(i+1);
if(m*(i+1)==n)
m-=1;
}
}*/
int erfen(ll l,ll r)
{
if(l==r)
return l;
ll mid=(l+r)/2+1;
if(n/mid==help)
return erfen(mid,r);
return erfen(l,mid-1);
}
int main()
{
while(scanf("%lld%lld",&m,&n)!=EOF)
{
ans=0;
if(m>=n)
{
ans+=(m-n)*n;
m=n-1;
}
ll now=1;
while(now<=m)
{
help=n/now;
ll last=erfen(now,m);
ans+=(2*n-help*(now+last))*(last-now+1)/2;
now=last+1;
}
printf("%lld\n",ans);
}
return 0;
}