【2019银联高校极客挑战赛 初赛 第二场】B. 码队弟弟的求和问题

题意:

计算:

\[\begin{eqnarray*} \sum\limits_{i = 1}^n \sum\limits_{j = 1}^m (ij(n \bmod i)(m \bmod j)) \bmod (10^9 + 7) \end{eqnarray*} \]

思路:
考虑\(x \bmod y = x - \left\lfloor \frac{x}{y} \right\rfloor \cdot y\),那么将式子化简,有:

\[\begin{eqnarray*} &&\sum\limits_{i = 1}^n \sum\limits_{j = 1}^m (ij(n - \left\lfloor \frac{n}{i} \right\rfloor \cdot i) (m - \left\lfloor \frac{m}{j} \right\rfloor \cdot j)) \bmod (10^9 + 7) \\ &=& \sum\limits_{i = 1}^n (i \cdot (n - \left\lfloor \frac{n}{i} \right\rfloor \cdot i)) \sum\limits_{j = 1}^m (j \cdot (m - \left\lfloor \frac{m}{j} \right\rfloor \cdot j)) \bmod (10^9 + 7) \end{eqnarray*} \]

然后分块计算即可。

代码:

#include <bits/stdc++.h>
using namespace std;

#define ll long long
const ll p = 1e9 + 7;
ll n, m, inv6;
ll qmod(ll base, ll n) {
	ll res = 1;
	while (n) {
		if (n & 1) res = res * base % p;
		base = base * base % p;
		n >>= 1;
	}
	return res;
}

ll f(ll x) {
	return (x * (x + 1) / 2) % p;
}

ll f2(ll x) {
	return x * (x + 1) % p * (2 * x + 1) % p * inv6 % p;
}

ll g(ll l, ll r) {
	return (f2(r) - f2(l - 1) + p) % p;
}

int main() {
	inv6 = qmod(6, p - 2);
	while (scanf("%lld%lld", &n, &m) != EOF) {
		ll tot = m * f(m) % p;
		for (int i = 1, j; i <= m; i = j + 1) {
			j = m / (m / i);
			tot -= 1ll * g(i, j) * (m / i) % p;
			tot = (tot + p) % p;	
		}
		ll res = n * f(n) % p * tot % p;
		for (int i = 1, j; i <= n; i = j + 1) {
			j = n / (n / i);
			res -= 1ll * g(i, j) * (n / i) % p * tot % p;
			res = (res + p) % p;
		}
		printf("%lld\n", res);
	}
	return 0;
}

posted @ 2019-07-22 07:51  Dup4  阅读(196)  评论(0)    收藏  举报