题目描述
http://acm.nyist.net/JudgeOnline/problem.php?pid=508
-
给你两个数n,k,请求出
的值。
-
输入
- 每行两个数n, k(1 <= n, k <= 10^9). 输出
- 输出和,每个结果占一行。 样例输入
-
5 4 5 3
样例输出
-
5 7
题目分析:
对于此题不能直接进行暴力,数值大,只能用sqrt(n)的算法,首先计算n%i的余数和,i=1~n;注意到:n%i=n/i*i;
因此我们可以模拟从i=1~sqrt(n);sum+=n%i;对于i对应的j=n/i,可以知道(n/i~n/i+1)==d;对与这组数,计算得到
s1=((n/i-n/(i+1))*n)-d*(n/(i+1)+1+......+n/i);sum+=s1;直到循环结束,就得到n%i的余数和,我们用ModSum(n)。
现在我们求k%i的余数和,i=1~n;进行分析k和n即可,
一、k<n res=ModSum(k)+(n-k)*k;注:当n>k时,k%n==k
二、k=n res=ModSum(k)
三、k>n res=ModSum(k); { for(int i=n+1;i<=n;i++)
res-=k%i;//减去多计算的值即可。
}
AC代码:
/**
*1、ModSum1():O(n)
*2、ModSum2():O(sqrt(n))
*1 2 3 4
*16 8 5 4
* 1 2 3
*/
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<cmath>
#define LL long long
#define MOD 1000000007
using namespace std;
LL ModSum1(LL n){
LL t=(n+1)/2-1;
LL sum=t*(t+1)/2;
for(LL i=1;i<=n/2;i++){
sum+=n-(n/i*i);
}
return sum;
}
LL ModSum2(LL n,LL k){
LL sum=0,n1=n;
n=k;
LL tem=sqrt(n);
for(LL i=1;i<=tem;i++){
if(n/i==i){
sum+=n-n/i*i;
continue;
}
sum+=n-n/i*i;
sum=sum;
//cout<<n/(i+1)<<" "<<n/i<<endl;
LL tt=n*(n/i-(n/(i+1)))-i*((n/i+(n/(i+1))+1)*(n/i-(n/(i+1)))/2);
//sum=(sum+(tt%MOD*i%MOD)%MOD)%MOD;
sum=(sum+tt);
}
//cout<<n1<<k<<endl;
if(k<=n1){
sum+=(n1-k)*k;
}
else {
for(LL i=n1+1;i<=k;i++){
sum-=k%i;
}
}
return sum;
}
int main()
{
long long n,k;
while(cin>>n>>k){
//LL sum1=ModSum1(n);
LL sum2;
sum2=ModSum2(n,k);
cout<<sum2<<endl;
}
return 0;
}