题目描述
http://acm.nyist.net/JudgeOnline/problem.php?pid=508
给你两个数n,k,请求出的值。
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; }
原文地址:http://blog.csdn.net/fool_ran/article/details/42498113