BZOJ 1257 Sum of remainder

http://www.lydsy.com/JudgeOnline/problem.php?id=1257

topic

Enter n, k and ask for \ [\ sum_ {i = 1} ^ nk \ bmod i \]

$1\leqslant n,k\leqslant 10^9$

answer

This is a topic of neerc2005

If it is directly counted as definitely overtime

$ k \ bmod i $ can be written as

\[k-\left\lfloor \frac{k}{i}\right\rfloor\times i\]

Playing watch will find that $ \ left \ lfloor \ frac {k} {i} \ right \ rfloor $ will sometimes be repeated

Then when is the construction repeated

Need to use

\[\left\lfloor\frac{k}{i}\right\rfloor\leqslant \left(\frac{k}{i}\right)\]

Then

\[\left\lfloor\frac{k}{\left\lfloor\frac{k}{\left\lfloor\frac{k}{i}\right\rfloor}\right\rfloor}\right\rfloor\leqslant\left\lfloor\frac{k}{\left\lfloor\frac{k}{\left(\frac{k}{i}\right)}\right\rfloor}\right\rfloor=\left\lfloor\frac{k}{\left\lfloor i\right\rfloor}\right\rfloor=\left\lfloor\frac{k}{i}\right\rfloor\]

\[\left\lfloor\frac{k}{\left\lfloor\frac{k}{\left\lfloor\frac{k}{i}\right\rfloor}\right\rfloor}\right\rfloor\geqslant\left\lfloor\frac{k}{\left(\frac{k}{\left\lfloor\frac{k}{i}\right\rfloor}\right)}\right\rfloor=\left\lfloor\left\lfloor\frac{k}{i}\right\rfloor\right\rfloor=\left\lfloor\frac{k}{i}\right\rfloor\]

and so

\[\left\lfloor\frac{k}{\left\lfloor\frac{k}{\left\lfloor\frac{k}{i}\right\rfloor}\right\rfloor}\right\rfloor=\left\lfloor\frac{k}{i}\right\rfloor\]

Obviously the middle part should also be equal, because if $ x <y $, then

\[\left\lfloor x\right\rfloor\leqslant\left\lfloor y\right\rfloor\]

This can speed up a part, but how much can it be accelerated?

Direct table verification:

int main() {
	ll i=1;
	int cnt=0;
	while(i<int(1e9)) {
		cnt++;
		printf("%10lld", i);
		i=int(1e9)/i;
		i=int(1e9)/i;
		i++;
	}
	printf("\n%d\n", cnt);
}

Get the worst case only 63244 cycles

Then, you can sum directly

\[\sum_{i=1}^n k\bmod i=nk-\sum_{i=1}^n \left\lfloor\frac{k}{i}\right\rfloor\times i\]

For each segment is equal, the second term is an arithmetic sequence, which can be over the time limit

Although it will not prove the time complexity, but it can save a lot of time for proof

AC code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define REPE(i,a,b) for(int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(int i=(a); i>=(b); i--)
using namespace std;
typedef long long ll;
int main() {
	int n,k; scanf("%d%d", &n, &k);
	ll i=1, ans=(ll)n*k;
	while(i<=n) {
		if(i>k) {
			break;
		} else {
			int j=k/(k/i);
			if(j>n) j=n;
			ans-=(i+j)*(k/i)*(j-i+1)/2;
			i=j+1;
		}
	}
	printf("%lld\n", ans);
}

 

Guess you like

Origin www.cnblogs.com/sahdsg/p/12708261.html