1. 程式人生 > >餘數求和(CQOI2007)

餘數求和(CQOI2007)

餘數求和

這是一道老題,但是作為一道省選題,它的程式碼卻短小精悍,可以觀賞。
我們只需要進行數學推導即可解決。(60分暴力分應該是可以秒拿的)
由題意得:
a n s = i

= 1 n k % i ans=\sum\limits_{i=1}^{n}k\%i
首先我們需要知道 a
% b a\%b
可以表示為 a b a
b a-b*\lfloor\frac{a}{b}\rfloor
這個應該是在程式碼中經常用到的
所以 a n s = i = 1 n k i k i = n k i = 1 n i k i ans=\sum\limits_{i=1}^{n}k-i*\lfloor\frac{k}{i}\rfloor=n*k-\sum\limits_{i=1}^{n}i*\lfloor\frac{k}{i}\rfloor
然後 k i \lfloor\frac{k}{i}\rfloor 可以分塊來做, k i \lfloor\frac{k}{i}\rfloor 大約有 k \sqrt k 種取值,所以時間複雜度 O ( k ) O(\sqrt k)

所以程式碼如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,k; 
int main(){
	scanf("%lld%lld",&n,&k);
	long long ans=n*k;
	for(long long l=1,r;l<=n;l=r+1) {
        if(k/l!=0) r=min(k/(k/l),n); 
        else r=n;
        ans-=(k/l)*(r-l+1)*(l+r)/2;
    }
	printf("%lld",ans);
	return 0;
}