|
2 | 2 | #define AFMT_FLOOR_SUM |
3 | 3 |
|
4 | 4 | // Calculate $\sum_{i = 0}^{n - 1} \lfloor \frac{ai + b}{m} \rfloor$ in $O(\min\{a, m, n\})$ |
5 | | -long long floor_sum( |
6 | | - long long a, long long b, long long m, long long n |
| 5 | +unsigned long long floor_sum_unsigned( |
| 6 | + unsigned long long a, unsigned long long b, |
| 7 | + unsigned long long m, unsigned long long n |
7 | 8 | ) { |
8 | | - if (a == 0) return b / m * n; |
9 | 9 | if (a >= m || b >= m) { |
10 | 10 | return (a / m) * (n * (n - 1) / 2) + b / m * n + |
11 | | - floor_sum(a % m, b % m, m, n); |
| 11 | + floor_sum_unsigned(a % m, b % m, m, n); |
12 | 12 | } |
13 | | - long long mx = (a * (n - 1) + b) / m; |
14 | | - return (n - 1) * mx - floor_sum(m, m - b - 1, a, mx); |
| 13 | + unsigned long long mx = (a * (n - 1) + b) / m; |
| 14 | + return mx ? (n - 1) * mx - floor_sum_unsigned(m, m - b - 1, a, mx) : 0; |
| 15 | +} |
| 16 | + |
| 17 | +// Calculate $\sum_{i = 0}^{n - 1} \lfloor \frac{ai + b}{m} \rfloor$ in $O(\min\{a, m, n\})$ |
| 18 | +long long floor_sum(long long a, long long b, long long m, long long n) { |
| 19 | + unsigned long long ans = 0; |
| 20 | + if (a < 0) { |
| 21 | + unsigned long long a2 = (a % m + m) % m; |
| 22 | + ans -= 1ull * n * (n - 1) / 2 * ((a2 - a) / m), a = a2; |
| 23 | + } |
| 24 | + if (b < 0) { |
| 25 | + unsigned long long b2 = (b % m + m) % m; |
| 26 | + ans -= 1ull * n * ((b2 - b) / m), b = b2; |
| 27 | + } |
| 28 | + return ans + floor_sum_unsigned(a, b, m, n); |
15 | 29 | } |
16 | 30 |
|
17 | 31 | #endif // !AFMT_FLOOR_SUM |
0 commit comments